多进程回声服务器/客户端【linux】

并发服务器端

 1 #include <unistd.h>
 2 #include <stdio.h>
 3 #include <sys/wait.h>
 4 #include <cstring>
 5 #include <arpa/inet.h>
 6 #include <signal.h>
 7 #include <cstdlib>
 8 #include <iostream>
 9 using namespace std;
10 void child_over(int sig)//信号处理器
11 {
12     int state;
13     int child_pid = waitpid(-1, &state, WNOHANG);
14     if(WIFEXITED(state))
15     {
16         printf("id = %d 的进程正常终止,返回值是 %d\n",
17                child_pid, WEXITSTATUS(state));
18     }
19 }
20 int main(int argc, char **argv)
21 {
22     int ser_sock, cli_sock;
23     char s[200];
24     sockaddr_in ser_addr, cli_addr;
25     struct sigaction act;
26     act.sa_handler = child_over;
27     sigemptyset(&act.sa_mask);
28     act.sa_flags = 0;
29     sigaction(SIGCHLD, &act, 0);//信号注册函数
30 
31     ser_sock = socket(PF_INET, SOCK_STREAM, 0);
32 
33     int opt = 1;
34     setsockopt(ser_sock, SOL_SOCKET, SO_REUSEADDR, &opt, 4);//端口地址再分配
35 
36     memset(&ser_addr, 0, sizeof(ser_addr));
37     ser_addr.sin_family = AF_INET;
38     ser_addr.sin_addr.s_addr = htonl(INADDR_ANY);
39     ser_addr.sin_port = htons(atoi(argv[1]));
40 
41     if(bind(ser_sock, (sockaddr *)&ser_addr, sizeof(ser_addr)) != 0)
42         puts("bind error");
43     if(listen(ser_sock, 5) != 0)
44         puts("listen error");
45 
46     while(1)
47     {
48         socklen_t s_len = sizeof(cli_addr);
49         cli_sock = accept(ser_sock, (sockaddr *)&cli_addr, &s_len);
50         if(cli_sock == -1) continue;
51 
52         pid_t pid = fork();
53         if(pid == 0)
54         {
55             close(ser_sock);
56             int len;
57             while(len = read(cli_sock, s, 100))
58             {
59                 if(!len) break;
60                 s[len] = 0;
61                 printf("message from client : %s\n", s);
62                 write(cli_sock, s, len);
63             }
64             close(cli_sock);
65             return 3;
66         }
67         else
68             close(cli_sock);
69     }
70     close(ser_sock);
71     return 0;
72 }

 

I/O分割的回声客户端

 

 1 #include <stdio.h>
 2 #include <arpa/inet.h>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <unistd.h>
 6 using namespace std;
 7 int main(int argc, char **argv)
 8 {
 9     int sock;
10     sockaddr_in ser_addr;
11     char s[200];
12     sock = socket(PF_INET, SOCK_STREAM, 0);
13     if(sock == -1) puts("socket error");
14     memset(&ser_addr, 0, sizeof(ser_addr));
15     ser_addr.sin_family = AF_INET;
16     ser_addr.sin_addr.s_addr = inet_addr(argv[1]);
17     ser_addr.sin_port = htons(atoi(argv[2]));
18     if(connect(sock, (sockaddr *)&ser_addr, sizeof(ser_addr)) == -1)
19         puts("connect error");
20 
21 
22     pid_t pid = fork();
23     if(pid == 0)
24     {
25         while(1)
26         {
27             puts("wait for message...");
28             scanf("%s", s);
29             if(!strcmp(s, "q") || !strcmp(s, "Q"))
30             {
31                 shutdown(sock, 1);
32                 break;
33             }
34             else
35                 write(sock, s, strlen(s));
36             sleep(0.5);
37         }
38     }
39     else
40     {
41         while(1)
42         {
43             int len = read(sock, s, 100);
44             if(len == 0) break;
45             s[len] = 0;
46             printf("message from server:%s\n", s);
47         }
48     }
49     close(sock);
50     return 0;
51 }

 

 

 

客户端31行用shutdown而不用close的原因是:


注意:
1.如果有多个进程共享一个套接字,close每被调用一次,计数减1,直到计数为0时,也就是所用进程都调用了close,套接字将被释放。
2.在多进程中如果一个进程中shutdown(sfd, SHUT_RDWR)后其它的进程将无法进行通信. 如果一个进程close(sfd)将不会影响到其它进程.
3.shutdown,不考虑描述符的参考数,可选择中止一个方向的连接, 但是仅仅是断开连接,仍然需要close释放链接占用的文件描述符。

posted @ 2018-09-01 15:05  LesRoad  阅读(604)  评论(0编辑  收藏  举报