前面已經編寫完基本的TCP服務器和客戶端了;現在要對服務器做一個改進版本的,前面的服務器,其實只支持一個訪問,因爲當我們監聽到一個程序的時候,本進程只能服務其一個socket;
現在來寫一個支持多用戶訪問的,其中有好幾個方法,可以來支持多用戶訪問;
- 可以使用多進程,每當監聽到一個請求時,就創建一個進程來讓子進程去爲他服務;這樣就可以再去監聽下一個請求了;
53 int id = fork();
54 if(id < 0 )
55 {
56 printf("fork error!\n");
57 exit(5);
58 }
59 else if(id == 0)
60 {//子進程來處理
61
62 while(1)
63 {
64 int id = fork();
65 if(id > 0 )//偷懶行爲,再創建一次,父進程退出,這樣就成孤兒進程在處理,最後由init進程管理
66 {
67 exit(0);
68 }
69 char buf[1024];
70 ssize_t s = read(client_sock,buf,sizeof(buf));
71 if(s>0)
72 {
73 buf[s] = 0;
74 printf("client :# %s\n",buf);
75 }
76 else
77 {
78 printf("read down ..........break;");
79 break;
80 }
81 write(client_sock,buf,sizeof(buf)-1);
82 }
83 }
84 else
85 {
86
87 }
這個樣子就實現了多進程的處理的;
2.同時也就有相應的多線程的版本,其實原理都是一樣的,監聽到了就拿出去創建一個新的線程來處理它就好了;
把處理請求邏輯拿出來封裝爲一個函數;
11 void* handlerRequest(void* arg)
12 {
13 int new_fd = (int)arg;
14 while(1)
15 {
16 char buf[1024];
17 ssize_t s= read(new_fd,buf,sizeof(buf)-1);
18 if(s > 0)
19 {
20 buf[s] = 0;
21 printf("client:%s\n",buf);
22 write(new_fd,buf,strlen(buf));
23 }
24 else
25 {
26 printf("read done....\n");
27 break;
28 }
29 }
30 }
然後再在接到請求的時候創建線程就好了;
75 pthread_t id;
76 pthread_create(&id,NULL,handlerRequest,(void*)client_sock);
77 pthread_detach(id);
這樣就可以了;
這裏還要研究一個問題就是,TCP連接中當我們最後申請斷開的一方是要進入TIME_WAIT狀態的,這個時候,如果是我們編寫的代碼的話,服務器自己斷開的,再重啓就要進入TIME_WAIT,這對現實中it公司可以大問題,服務器掛掉起不起來;
所以就有了一個解決方案,使⽤setsockopt()設置socket描述符的 選項SO_REUSEADDR爲1,表⽰允許創建端⼜號相同但IP地址不同的多個socket描述符。
這個樣子就好了,如果是服務器掛掉也可以立即重啓了;