门窗网站设计,个人主页排版,网站建设类岗位,如何免费申请网站域名一.思路
实现一个服务器可以连接多个客户端#xff0c;每当accept函数等待到客户端进行连接时 就创建一个子进程; 核心思路#xff1a;让accept循环阻塞等待客户端#xff0c;每当有客户端连接时就fork子进程#xff0c;让子进程去和客户端进行通信#xff0c;父进程用于…一.思路
实现一个服务器可以连接多个客户端每当accept函数等待到客户端进行连接时 就创建一个子进程; 核心思路让accept循环阻塞等待客户端每当有客户端连接时就fork子进程让子进程去和客户端进行通信父进程用于监听并使用信号捕捉回收子进程(子进程关闭用于监听的套接字lfd父进程关闭用于通信的cfd)
二.多进程并发服务器代码实现:
1.利用while 和 accept 阻塞等待客户端连接一旦有一个客户端连接上就创建一个新的子进程执行服务逻辑。 2.子进程结束时利用信号捕捉函数sigaction回收子进程 3.注意当主进程阻塞在accept时若子进程发出信号accept会被打断(一系列慢速系统调用的特点)从而直接执行接下来的fork函数这就会导致一个子进程刚好被回收后又会产生一个新的子进程为了防止这种情况使用again和goto维护accept防止被信号打断后产生错误。 1 #includeiostream 2 #includeunistd.h3 #includesys/socket.h4 #includearpa/inet.h5 #includesignal.h6 #includesys/wait.h7 using namespace std;8 9 void huidiao(int signo)10 {11 pid_t pid;12 while((pid waitpid(-1,NULL,WNOHANG))0)13 {14 coutpidendl;15 }16 return ;17 }18 19 int main()20 { 21 struct sigaction act;22 act.sa_handler huidiao; sigemptyset(act.sa_mask);24 act.sa_flags 0;25 sigaction(SIGCHLD,act,NULL);26 //socket bind listen accept27 int fd socket(AF_INET,SOCK_STREAM,0);28 struct sockaddr_in serveraddr,clientaddr;29 serveraddr.sin_family AF_INET;30 serveraddr.sin_port htons(9876);31 serveraddr.sin_addr.s_addr htonl(INADDR_ANY);32 bind(fd,(struct sockaddr*)serveraddr,sizeof(serveraddr));33 34 listen(fd,128);35 36 socklen_t clientaddr_len sizeof(clientaddr);37 int sfd,flag;38 while(true)39 {40 sfd accept(fd,(struct sockaddr*)clientaddr,clientaddr_len);41 flag fork();42 43 if(flag 0)44 { close(fd);46 break;47 }48 else if(flag 0)49 {50 exit(1);51 }52 else if(flag0) 53 {54 close(sfd);55 continue;56 }57 } 58 59 if(flag 0)60 { 61 for(;;)62 {63 char buf[1024];64 int n read(sfd,buf,sizeof(buf));65 if(n0)66 { close(sfd);68 coutjieshuendl;69 exit(0);70 }71 for(int i 0;in;i)72 {73 buf[i] toupper(buf[i]);74 }75 write(STDOUT_FILENO,buf,n);76 write(sfd,buf,n);77 }78 }79 return 0;80 }三. 多线程并发服务器代码实现
1.#include stdio.h
2.#include string.h
3.#include arpa/inet.h
4.#include pthread.h
5.#include ctype.h
6.#include unistd.h
7.#include fcntl.h
8.
9.#include wrap.h
10.
11.#define MAXLINE 8192
12.#define SERV_PORT 8000
13.
14.struct s_info { //定义一个结构体, 将地址结构跟cfd捆绑
15. struct sockaddr_in cliaddr;
16. int connfd;
17.};
18.
19.void *do_work(void *arg)
20.{
21. int n,i;
22. struct s_info *ts (struct s_info*)arg;
23. char buf[MAXLINE];
24. char str[INET_ADDRSTRLEN]; //#define INET_ADDRSTRLEN 16 可用[d查看
25.
26. while (1) {
27. n Read(ts-connfd, buf, MAXLINE); //读客户端
28. if (n 0) {
29. printf(the client %d closed...\n, ts-connfd);
30. break; //跳出循环,关闭cfd
31. }
32. printf(received from %s at PORT %d\n,
33. inet_ntop(AF_INET, (*ts).cliaddr.sin_addr, str, sizeof(str)),
34. ntohs((*ts).cliaddr.sin_port)); //打印客户端信息(IP/PORT)
35.
36. for (i 0; i n; i)
37. buf[i] toupper(buf[i]); //小写--大写
38.
39. Write(STDOUT_FILENO, buf, n); //写出至屏幕
40. Write(ts-connfd, buf, n); //回写给客户端
41. }
42. Close(ts-connfd);
43.
44. return (void *)0;
45.}
46.
47.int main(void)
48.{
49. struct sockaddr_in servaddr, cliaddr;
50. socklen_t cliaddr_len;
51. int listenfd, connfd;
52. pthread_t tid;
53.
54. struct s_info ts[256]; //创建结构体数组.
55. int i 0;
56.
57. listenfd Socket(AF_INET, SOCK_STREAM, 0); //创建一个socket, 得到lfd
58.
59. bzero(servaddr, sizeof(servaddr)); //地址结构清零
60. servaddr.sin_family AF_INET;
61. servaddr.sin_addr.s_addr htonl(INADDR_ANY); //指定本地任意IP
62. servaddr.sin_port htons(SERV_PORT); //指定端口号
63.
64. Bind(listenfd, (struct sockaddr *)servaddr, sizeof(servaddr)); //绑定
65.
66. Listen(listenfd, 128); //设置同一时刻链接服务器上限数
67.
68. printf(Accepting client connect ...\n);
69.
70. while (1) {
71. cliaddr_len sizeof(cliaddr);
72. connfd Accept(listenfd, (struct sockaddr *)cliaddr, cliaddr_len); //阻塞监听客户端链接请求
73. ts[i].cliaddr cliaddr;
74. ts[i].connfd connfd;
75.
76. pthread_create(tid, NULL, do_work, (void*)ts[i]);
77. pthread_detach(tid); //子线程分离,防止僵线程产生.
78. i;
79. }
80.
81. return 0;
82.}