多进程服务器Demo

  今天实现的这个服务器程序加入了对多个客户端同时请求处理的实现,服务器端通过对每次监听到的客户端程序新建一个子进程,进行相关的处理,将从客户端传来的字符串数据,转化为大写的字符串序列,然重新写回到connfd;另一方面,客户端通过在标准输入里获取客户输入到的字符串序列,传送到connfd,再从connfd读取经服务器处理过的字符串序列打印到标准输出上。

  同时,加上了对某些socket原语函数的封装处理,主要封装了对出错的处理机制,基本原语函数都以相应大写首个字符的命名表示,定义在“wrap.c”和“wrap.h”文件中。

wrap.h

  1 /* wrap.h */
  2 #ifndef __WRAP_H_
  3 #define __WRAP_H_
  4
  5 void perr_exit(const char *s);
  6 int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr);
  7 void Bind(int fd, const struct sockaddr *sa, socklen_t salen);
  8 void Connect(int fd, const struct sockaddr *sa, socklen_t salen);
  9 void Listen(int fd, int backlog);
 10 int Socket(int family, int type, int protocol);
 11 ssize_t Read(int fd, void *ptr, size_t nbytes);
 12 ssize_t Write(int fd, const void *ptr, size_t nbytes);
 13 void Close(int fd);
 14 ssize_t Readn(int fd, void *vptr, size_t n);
 15 ssize_t Writen(int fd, const void *vptr, size_t n);
 16 static ssize_t my_read(int fd, char *ptr);
 17 ssize_t Readline(int fd, void *vptr, size_t maxlen);
 18
 19 #endif

wrap.c

  1 /*wrap.c */
  2 #include<stdlib.h>
  3 #include<errno.h>
  4 #include<sys/socket.h>
  5
  6 void perr_exit(const char* s)
  7 {
  8     perror(s);
  9     exit(1);
 10 }
 11
 12 int Accept(int fd,struct sockaddr *sa,socklen_t *salenptr)
 13 {
 14     int n;
 15 again:
 16     if((n=accept(fd,sa,salenptr))<0){
 17         if((errno==ECONNABORTED)||(errno==EINTR))
 18             goto again;
 19         else
 20             perr_exit("accept error");
 21     }
 22     return n;
 23 }
 24
 25 void Bind(int fd,const struct sockaddr *sa,socklen_t salen)
 26 {
 27     if(bind(fd,sa,salen)<0)
 28         perr_exit("bind error");
 29 }
 30
 31 void Connect(int fd,const struct sockaddr *sa,socklen_t salen)
 32 {
 33     if(connect(fd,sa,salen)<0)
 34         perr_exit("connect error");
 35 }
 36
 37 void Listen(int fd,int backlog)
 38 {
 39     if(listen(fd,backlog)<0)
 40         perr_exit("listen error");
 41 }
 42
 43 int Socket(int family,int type,int protocol)
 44 {
 45     int n;
 46     if((n=socket(family,type,protocol))<0)
 47         perr_exit("socket error");
 48     return n;
 49 }
 50
 51 ssize_t Read(int fd,void *ptr,size_t nbytes)
 52 {
 53     ssize_t n;
 54 again:
 55     if((n=read(fd,ptr,nbytes))==-1){
 56         if(errno==EINTR)
 57             goto again;
 58         else
 59             return -1;
 60     }
 61     return n;
 62 }
 63
 64 ssize_t Write(int fd,const void *ptr,size_t nbytes)
 65 {
 66     ssize_t n;
 67 again:
 68     if((n=write(fd,ptr,nbytes))==-1){
 69         if(errno==EINTR)
 70             goto again;
 71         else
 72             return -1;
 73     }
 74     return n;
 75 }
 76
 77 void Close(int fd)
 78 {
 79     if(close(fd)==-1)
 80         perr_exit("close error");
 81 }
 82
 83 ssize_t Readn(int fd,void *vptr,ssize_t n)
 84 {
 85     size_t nleft;
 86     ssize_t nread;
 87     char *ptr;
 88     ptr=vptr;
 89     nleft=n;
 90     while(nleft>0){
 91         if((nread=read(fd,ptr,nleft))<0){
 92             if(errno==EINTR)
 93                 nread=0;
 94             else
 95                 return -1;
 96         }else if(nread==0)
 97             break;
 98         nleft-=nread;
 99         ptr+=nread;
100     }
101     return n-nleft;
102 }
103
104
105 ssize_t Writen(int fd,const void *vptr,size_t n)
106 {
107     size_t nleft;
108     ssize_t nwritten;
109     const char* ptr;
110     ptr=vptr;
111     nleft=n;
112     while(nleft>0){
113         if(nwritten=write(fd,ptr,nleft)<=0){
114             if(nwritten<0&&errno==EINTR)
115                 nwritten=0;
116             else
117                 return -1;
118         }
119         nleft-=nwritten;
120         ptr+=nwritten;
121     }
122     return n;
123 }
124
125 static ssize_t my_read(int fd,char* ptr)
126 {
127     static int read_cnt;
128     static char *read_ptr;
129     static char read_buf[100];
130     if(read_cnt<=0){
131 again:
132         if((read_cnt=read(fd,read_buf,sizeof(read_buf)))<0){
133             if(errno==EINTR)
134                 goto again;
135             else
136                 return -1;
137         }else if(read_cnt==0)
138             return 0;
139         read_ptr=read_buf;
140     }
141     read_cnt--;
142     *ptr=*read_ptr++;
143     return 1;
144 }
145
146 ssize_t Readline(int fd,void *vptr,size_t maxlen)
147 {
148     ssize_t n,rc;
149     char c,*ptr;
150     ptr=vptr;
151     for(n=1;n<maxlen;n++){
152         if((rc=my_read(fd,&c))==1){
153             *ptr++=c;
154             if(c==‘\n‘)
155                 break;
156         }else if(rc==0){
157             *ptr=0;
158             return n-1;
159         }else
160             return -1;
161     }
162     *ptr=0;
163     return n;
164 }
165 

服务器端:

  1 #include<stdlib.h>
  2 #include<stdio.h>
  3 #include<unistd.h>
  4 #include<string.h>
  5 #include<netinet/in.h>
  6 #include<sys/types.h>
  7 #include<sys/socket.h>
  8 #include<arpa/inet.h>
  9 #include "wrap.c"
 10 #define SERVER_PORT 8000
 11 #define BUFSIZE 80
 12 int main(int argc,char* argv[])
 13 {
 14     struct sockaddr_in serveraddr,clientaddr;
 15     int listenfd,connfd,len,clientaddr_len,i;
 16     char buf[BUFSIZE];
 17     char str[BUFSIZE];
 18     pid_t pid;
 19     listenfd=Socket(AF_INET,SOCK_STREAM,0);
 20
 21     bzero(&serveraddr,sizeof(serveraddr));
 22     serveraddr.sin_family=AF_INET;
 23     serveraddr.sin_addr.s_addr=htonl(INADDR_ANY);
 24     serveraddr.sin_port=htons(SERVER_PORT);
 25
 26     Bind(listenfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));
 27
 28     Listen(listenfd,128);
 29     printf("waiting for connecting\n");
 30     while(1){
 31         clientaddr_len=sizeof(clientaddr);
 32         connfd=Accept(listenfd,(struct sockaddr *)&clientaddr,&clientaddr_len);
 33         printf("client ip: %s\tport :%d\n",inet_ntop(AF_INET,&clientaddr.sin_addr.s_addr,str,sizeof(str)),ntohs(clientaddr.sin_port));
 34         pid=fork();
 35         if(pid==0){
 36                 Close(listenfd);
 37                 while(1){
 38                     len=Read(connfd,buf,sizeof(buf));
 39                     for(i=0;i<len;i++)
 40                         buf[i]=toupper(buf[i]);
 41                     Write(connfd,buf,len);
 42                 }
 43                 Close(connfd);
 44                 return 0;
 45         }else if(pid>0){
 46                 Close(connfd);
 47         }
 48         else{
 49             //error deal
 50         }
 51     }
 52 //  Close(listenfd);
 53     return 0;
 54 }

客户端:

  1 #include<stdlib.h>
  2 #include<stdio.h>
  3 #include<string.h>
  4 #include<sys/types.h>
  5 #include<netinet/in.h>
  6 #include<sys/socket.h>
  7 #include<unistd.h>
  8 #include "wrap.c"
  9 #define SERVER_PORT 8000
 10 #define BUFSIZE 80
 11 int main(int argc,char* argv[])
 12 {
 13     int confd,len;
 14     struct sockaddr_in serveraddr;
 15     confd=Socket(AF_INET,SOCK_STREAM,0);
 16     char buf[BUFSIZE];
 17
 18     bzero(&serveraddr,sizeof(serveraddr));
 19     serveraddr.sin_family=AF_INET;
 20     inet_pton(AF_INET,"127.0.0.1",&serveraddr.sin_addr.s_addr);
 21     serveraddr.sin_port=htons(SERVER_PORT);
 22
 23     Connect(confd,(struct sockaddr*)&serveraddr,sizeof(serveraddr));
 24     while(fgets(buf,sizeof(buf),stdin)){
 25         Write(confd,buf,strlen(buf));
 26         len=Read(confd,buf,BUFSIZE);
 27         printf("the result from server:\n");
 28         Write(STDOUT_FILENO,buf,len);
 29     }
 30
 31     Close(confd);
 32     return 0;
 33 }
时间: 2024-12-20 06:56:14

多进程服务器Demo的相关文章

Linux socket多进程服务器框架一

重点:socket共用方法中错误码的定义以及错误码的解析 底层辅助代码 //serhelp.h #ifndef _vxser #define _vxser #ifdef __cplusplus extern "C" { #endif /** * sersocket_init - socket初始化 * @listenfd:文件描述符 * 成功返回0,失败返回错误码 * */ int sersocket_init(int *listenfd); /** * listen_socket -

linux编程实例--简单多进程服务器

主要利用fork事先创建若干个进程,并发处理多个客户端的连接,返回当前系统时间.具体代码如下: server.c # include <sys/types.h> # include <sys/socket.h> # include <netinet/in.h> # include <time.h> # include <string.h> # include <stdio.h> # include <signal.h> #

基于进程池的多进程服务器通信

代码来源:游双的linux高性能服务器编程 主进程创建一个进程池,当有客户端发送请求时,主进程选择一个进程与该客户端进行通信,为了简单期间,去掉了一些信号处理代码,其中信号的用法可以参考基于多进程的网络聊天程序 服务器代码如下: #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <assert.h&

1高并发服务器:多进程服务器

 1多进程并发服务器 使用多进程并发服务器时要考虑以下几点: A.父最大文件描述个数(父进程中需要close关闭accept返回的新文件描述符) B.系统内创建进程个数(和内存大小相关) C.进程创建过多是否降低整体服务性能(进程调度) 2.案例说明 server.c,代码如下: #include <stdio.h> #include <string.h> #include <netinet/in.h> #include <arpa/inet.h> #i

Linux socket多进程服务器框架二

客户端未解决Bug:子进程或者父进程退出的时候,我无法做到两个进程都调用clt_socket_Destory()方式释放socket句柄, 但是进程退出后,相应的资源也会释放,有一定影响,但是不大,以后我想到办法再优化.重点:客户端connect服务器方法需要单独分离出来,方便用户自己断线重连. 客户端 //clthelp.h #include <stdio.h> #include "commsocket.h" #ifndef _vxclt #define _vxclt #

Linux环境下HTTP服务器demo

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <netinet/in.h> #include <sys/socket.h> #define BUF_LEN 1028 // 1028 ever #define PORT 8000 const static char html_re_hd_su[] = "HTTP/1.1 200 OK\r\nConte

Linux socket多进程服务器框架三

在使用select管理服务器连接的时候: 注意1:select是可中断睡眠函数,需要屏蔽信号 注意2:必须获取select的返回值nread,每次处理完一个事件,nread需要-1 注意3:如果客户端的连接超过连接池的大小,需要关闭客户端连接 注意4:获取最大套接字的方法是每次有客户端连接过来时,在和maxfd比较,这样就不用每次select之前都遍历池,查找最大值 服务器 //serhelp.h #ifndef _vxser #define _vxser #ifdef __cplusplus

Linux 网络编程六(多进程服务器僵尸进程解决方案)

僵尸进程解决方案 1.忽略SIGCHLD信号,这样不会出现僵尸进程 2.安装信号,父进程接收到SIGCHLD信号后,wait()子进程 注意:这里的客户端有两个进程,一个接收信息,一个发送信息,当客户端退出时,会将sockfd套接字关闭两次 //头文件 int server_socket(); int client_socket(); //服务器端 #include "pub.h" int main(int arg,char *args[]) { server_socket(); re

Nodejs + express + ejs 之服务器demo

var http=require("http"); var express=require("express"); var fs = require("fs"); var bodyParser = require('body-parser'); var Common = require("./publice/common"); var app=express(); // 定时器 var refTimer = null; var