生活随笔
收集整理的這篇文章主要介紹了
Linux C++ 回射服务器
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
http://blog.csdn.net/qq_25425023/article/details/53914820
回射服務(wù)器就是服務(wù)端將客戶端的數(shù)據(jù)發(fā)送回去。
??
? 我實(shí)現(xiàn)的回射服務(wù)器返回增加了時(shí)間。
? 服務(wù)端代碼,可以很容易看懂:
?
[cpp] ?view plain
?copy #include?<sys/socket.h> ?? #include?<stdio.h> ?? #include?<string.h> ?? #include?<sys/types.h> ?? #include?<netinet/in.h> ?? #include?<time.h> ?? #include?<unistd.h> ?? #include?<arpa/inet.h> ?? #include?<stdlib.h> ?? ?? #include?"../thread_pool.h"??//在上一篇博客中 ?? ?? #define?MAX_BUFFER?512 ?? ?? typedef ? struct ?sockaddr?SSA;?? ?? char ?timebuffer[50];?? ?? char ?readbuffer[MAX_BUFFER];??? ?? time_t ?tick;?? ?? class ?task?? {?? private :?? ????int ?connfd;?? ?? public :?? ????task(int ?conn)?:?connfd(conn)?? ????{?? ????}?? ????~task(){}?? ?? ????void ?doit()?? ?? ????{?? ????size_t ?readsize;?? ????while ((readsize?=?read(connfd,?readbuffer,?MAX_BUFFER))?>?0)?? ?? ????{?? ????????printf("%ld?get?%dbyte\n" ,(unsigned? long )pthread_self()?? ?????????,?(int )readsize);??? ?? ????????if (readsize?==?-1)?? ?? ????????{?? ????????printf("errno?is?%s\n" ,?strerror(errno));? ?? ????????continue ;?? ????????}?? ????????readbuffer[readsize]?=?'\0' ;??? ????????tick?=?time(NULL);??? ????????????snprintf(timebuffer,?sizeof (timebuffer),? "time?:?%.24s\r\n" ,??? ????????ctime(&tick));?? ????????strcat(readbuffer,?timebuffer);???? ?????????? ????????write(connfd,?readbuffer,?strlen(readbuffer));???? ????}?? ?? ?? ?? ????close(connfd);?? ????}?? };?? ?? int ?main( int ?argc,? char ?*argv[])?? {?? ????if (argc?!=?2)?? ????{?? ????printf("uasge?:?%s?port" ,?argv[0]);?? ????exit(-1);?? ????}?? ????int ?sockfd,?connfd;?? ????struct ?sockaddr_in?serv_addr,?cli_addr;?? ????int ?port?=?atoi(argv[1]);?? ?????? ????serv_addr.sin_family?=?AF_INET;?? ????serv_addr.sin_port?=?htons(port);?? ????serv_addr.sin_addr.s_addr?=?htonl(INADDR_ANY);???? ?????? ????sockfd?=?socket(AF_INET,?SOCK_STREAM,?0);?? ????if (sockfd?<?0)?? ????{?? ????printf("socket?error'?n" );?? ????exit(-1);?? ????}?? ?????? ????bind(sockfd,?(SSA?*)&serv_addr,?sizeof (serv_addr));?? ?????? ????listen(sockfd,?6);?? ?????? ????threadpool<task>?pool(60,?100);?? ????pool.start();???? ????while (1)?? ????{?? ????socklen_t?len?=?sizeof (cli_addr);?? ????connfd?=?accept(sockfd,?(SSA?*)&cli_addr,?&len);???? ????task?*ta?=?new ?task(connfd);??? ?? ????char ?buf[20];?? ????printf("IP?%s?conn\n" ,?inet_ntop(AF_INET,?&cli_addr.sin_addr,?buf,??? ????????sizeof (buf)));?? ????????while (!pool.append_task(ta))?? ?? ????????printf("loop\n" );? ?? ????}?? ????return ?0;?? }??
下面的是客戶端的代碼:
[cpp] ?view plain
?copy #include?<stdio.h> ?? #include?<sys/socket.h> ?? #include?<arpa/inet.h> ?? #include?<string.h> ?? #include?<sys/types.h> ?? #include?<unistd.h> ?? #include?<netinet/in.h> ?? #include?<stdlib.h> ?? ?? int ?main( int ?argc,? char ?*argv[])?? {?? ????if (argc?!=?3)? ?? ????{?? ????printf("usage:?%s?ip?port\n" ,?argv[0]);?? ????exit(-1);?? ????}?? ????int ?sockfd;?? ????struct ?sockaddr_in?serv_addr;?? ????int ?port?=?atoi(argv[2]);?? ?? ?????? ????serv_addr.sin_family?=?AF_INET;?? ????serv_addr.sin_port?=?htons(port);???? ????inet_pton(AF_INET,?argv[1],?&serv_addr.sin_addr);?? ?????? ????sockfd?=?socket(AF_INET,?SOCK_STREAM,?0);?? ?????? ????connect(sockfd,?(struct ?sockaddr?*)&serv_addr,??? ????????sizeof (serv_addr));?? ????char ?buffer[50];?? ????write(sockfd,?"hello\n" ,?6);?? ?? ????shutdown(sockfd,?SHUT_WR);???? ????size_t ?num?=?read(sockfd,?buffer,? sizeof (buffer));?? ?? ????buffer[num]?=?'\0' ;?? ????printf("read:?%s\n" ,?buffer);?? ????shutdown(sockfd,?SHUT_RD);?? ?? ????return ?0;?? }??
客戶端一開(kāi)始我使用的是最后來(lái)個(gè)close的,就是注釋那部分,但是多個(gè)連接同時(shí)來(lái)的時(shí)候,服務(wù)端會(huì)出錯(cuò),具體的出錯(cuò)信息是:Connection reset by peer,重新執(zhí)行read之后,得到Hello的個(gè)數(shù)沒(méi)有少,也就是客戶端發(fā)送的個(gè)數(shù)。
然而我客戶端寫(xiě)完數(shù)據(jù),就關(guān)閉寫(xiě)端,讀取完數(shù)據(jù),再關(guān)閉讀端,就不會(huì)出現(xiàn)這樣的錯(cuò)誤。
具體原因還不是很清楚,網(wǎng)上沒(méi)有查找到具體的答案。求大神來(lái)解答!!~~
==============================================
終于知道原因了,出錯(cuò)的是在服務(wù)端的read函數(shù),read返回-1,而在客戶端,發(fā)送完數(shù)據(jù),就shutdown寫(xiě)端,發(fā)送完數(shù)據(jù),就會(huì)發(fā)送FIN包,服務(wù)端read返回0,因?yàn)閞ead不止被調(diào)用一次,第一次讀取完數(shù)據(jù)之后,繼續(xù)讀取,可是客戶端沒(méi)有數(shù)據(jù)可讀,就會(huì)出錯(cuò),而提前關(guān)閉客戶端寫(xiě)端,所以read那里的WHILE退出,就沒(méi)有了出錯(cuò)的信息。
同時(shí)寫(xiě)了兩個(gè)shell文件來(lái)測(cè)試:
[html] ?view plain
?copy #!/bin/bash?? ?? for?i?in?`seq?2000`??? do?? ????./client.out?127.0.0.1?8989?? done??
循環(huán) 執(zhí)行2000次。
第二個(gè)shell文件:
[html] ?view plain
?copy #!/bin/bash?? ?? ./loop.sh?> ?file1?&?? ./loop.sh?> ?file2?&?? ./loop.sh?> ?file3?&?? ./loop.sh?> ?file4?&?? ./loop.sh?> ?file5?&?? wait??
開(kāi)啟5個(gè)進(jìn)程來(lái)返問(wèn)。
執(zhí)行第二個(gè)shell文件
最終,耗時(shí)為:
[html] ?view plain
?copy real????0m7.589s?? user????0m0.460s?? sys?0m1.944s??
而且五個(gè)File文件中,有Hello的行數(shù)數(shù)都為2000.
下一篇是實(shí)現(xiàn)一個(gè)簡(jiǎn)單小型的web服務(wù)器。
總結(jié)
以上是生活随笔 為你收集整理的Linux C++ 回射服务器 的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。