Linux C++ 回射服務器

http://blog.csdn.net/qq_25425023/article/details/53914820

回射服務器就是服務端將客戶端的數據發送回去。

??

? 我實現的回射服務器返回增加了時間。


? 服務端代碼,可以很容易看懂:

?

[cpp]?view plain?copy
  1. #include?<sys/socket.h>??
  2. #include?<stdio.h>??
  3. #include?<string.h>??
  4. #include?<sys/types.h>??
  5. #include?<netinet/in.h>??
  6. #include?<time.h>??
  7. #include?<unistd.h>??
  8. #include?<arpa/inet.h>??
  9. #include?<stdlib.h>??
  10. ??
  11. #include?"../thread_pool.h"??//在上一篇博客中??
  12. ??
  13. #define?MAX_BUFFER?512??
  14. ??
  15. typedef?struct?sockaddr?SSA;??
  16. ??
  17. char?timebuffer[50];??//存儲時間??
  18. char?readbuffer[MAX_BUFFER];???//存儲客戶端數據??
  19. time_t?tick;??
  20. //任務類??
  21. class?task??
  22. {??
  23. private:??
  24. ????int?connfd;??//與客戶端連接的文件描述符??
  25. public:??
  26. ????task(int?conn)?:?connfd(conn)??
  27. ????{??
  28. ????}??
  29. ????~task(){}??
  30. ??
  31. ????void?doit()??//線程池調用函數??
  32. ????{??
  33. ????size_t?readsize;??
  34. ????while((readsize?=?read(connfd,?readbuffer,?MAX_BUFFER))?>?0)??//讀取客戶端數據??
  35. ????{??
  36. ????????printf("%ld?get?%dbyte\n",(unsigned?long)pthread_self()??
  37. ?????????,?(int)readsize);???//測試用??
  38. ????????if(readsize?==?-1)??//read出錯??
  39. ????????{??
  40. ????????printf("errno?is?%s\n",?strerror(errno));?//這里輸出"onnection?reset?by?peer"??
  41. ????????continue;??
  42. ????????}??
  43. ????????readbuffer[readsize]?=?'\0';???
  44. ????????tick?=?time(NULL);?//獲取時間??
  45. ????????????snprintf(timebuffer,?sizeof(timebuffer),?"time?:?%.24s\r\n",???
  46. ????????ctime(&tick));??
  47. ????????strcat(readbuffer,?timebuffer);??//時間與客戶數據連接到一起??
  48. ??????????
  49. ????????write(connfd,?readbuffer,?strlen(readbuffer));??//發送給客戶端??
  50. ????}??
  51. //??printf("close?the?connfd\n");??
  52. //??fflush(stdout);??
  53. ??
  54. ????close(connfd);??
  55. ????}??
  56. };??
  57. ??
  58. int?main(int?argc,?char?*argv[])??
  59. {??
  60. ????if(argc?!=?2)??
  61. ????{??
  62. ????printf("uasge?:?%s?port",?argv[0]);??
  63. ????exit(-1);??
  64. ????}??
  65. ????int?sockfd,?connfd;??
  66. ????struct?sockaddr_in?serv_addr,?cli_addr;??
  67. ????int?port?=?atoi(argv[1]);??
  68. ????//初始化sockaddr_in??
  69. ????serv_addr.sin_family?=?AF_INET;??
  70. ????serv_addr.sin_port?=?htons(port);??
  71. ????serv_addr.sin_addr.s_addr?=?htonl(INADDR_ANY);??//允許任何人連接??
  72. ????//創建套接字??
  73. ????sockfd?=?socket(AF_INET,?SOCK_STREAM,?0);??
  74. ????if(sockfd?<?0)??
  75. ????{??
  76. ????printf("socket?error'?n");??
  77. ????exit(-1);??
  78. ????}??
  79. ????//綁定??
  80. ????bind(sockfd,?(SSA?*)&serv_addr,?sizeof(serv_addr));??
  81. ????//監聽套接字??
  82. ????listen(sockfd,?6);??
  83. ????//創建線程池??
  84. ????threadpool<task>?pool(60,?100);??
  85. ????pool.start();??//開啟線程池??
  86. ????while(1)??
  87. ????{??
  88. ????socklen_t?len?=?sizeof(cli_addr);??
  89. ????connfd?=?accept(sockfd,?(SSA?*)&cli_addr,?&len);??//接受連接??
  90. ????task?*ta?=?new?task(connfd);???//新建任務??
  91. ????char?buf[20];??
  92. ????printf("IP?%s?conn\n",?inet_ntop(AF_INET,?&cli_addr.sin_addr,?buf,???
  93. ????????sizeof(buf)));??
  94. ????????while(!pool.append_task(ta))??//添加任務到任務隊列??
  95. ????????printf("loop\n");?//測試用??
  96. ????}??
  97. ????return?0;??
  98. }??

下面的是客戶端的代碼:

[cpp]?view plain?copy
  1. #include?<stdio.h>??
  2. #include?<sys/socket.h>??
  3. #include?<arpa/inet.h>??
  4. #include?<string.h>??
  5. #include?<sys/types.h>??
  6. #include?<unistd.h>??
  7. #include?<netinet/in.h>??
  8. #include?<stdlib.h>??
  9. ??
  10. int?main(int?argc,?char?*argv[])??
  11. {??
  12. ????if(argc?!=?3)?//參數不對,退出??
  13. ????{??
  14. ????printf("usage:?%s?ip?port\n",?argv[0]);??
  15. ????exit(-1);??
  16. ????}??
  17. ????int?sockfd;??
  18. ????struct?sockaddr_in?serv_addr;??
  19. ????int?port?=?atoi(argv[2]);??//將字符串的端口轉換稱int??
  20. ????//初始化服務端的端口和IP地址??
  21. ????serv_addr.sin_family?=?AF_INET;??
  22. ????serv_addr.sin_port?=?htons(port);??//將主機字節序轉換稱網絡字節序??
  23. ????inet_pton(AF_INET,?argv[1],?&serv_addr.sin_addr);??
  24. ????//創建套接字??
  25. ????sockfd?=?socket(AF_INET,?SOCK_STREAM,?0);??
  26. ????//連接??
  27. ????connect(sockfd,?(struct?sockaddr?*)&serv_addr,???
  28. ????????sizeof(serv_addr));??
  29. ????char?buffer[50];??
  30. ????write(sockfd,?"hello\n",?6);??//寫數據??
  31. ????shutdown(sockfd,?SHUT_WR);??//解釋在下面??
  32. ????size_t?num?=?read(sockfd,?buffer,?sizeof(buffer));??//讀數據??
  33. ????buffer[num]?=?'\0';??
  34. ????printf("read:?%s\n",?buffer);??
  35. ????shutdown(sockfd,?SHUT_RD);??
  36. //????close(sockfd);??
  37. ????return?0;??
  38. }??

客戶端一開始我使用的是最后來個close的,就是注釋那部分,但是多個連接同時來的時候,服務端會出錯,具體的出錯信息是:Connection reset by peer,重新執行read之后,得到Hello的個數沒有少,也就是客戶端發送的個數。

然而我客戶端寫完數據,就關閉寫端,讀取完數據,再關閉讀端,就不會出現這樣的錯誤。

具體原因還不是很清楚,網上沒有查找到具體的答案。求大神來解答!!~~

==============================================

終于知道原因了,出錯的是在服務端的read函數,read返回-1,而在客戶端,發送完數據,就shutdown寫端,發送完數據,就會發送FIN包,服務端read返回0,因為read不止被調用一次,第一次讀取完數據之后,繼續讀取,可是客戶端沒有數據可讀,就會出錯,而提前關閉客戶端寫端,所以read那里的WHILE退出,就沒有了出錯的信息。


同時寫了兩個shell文件來測試:

[html]?view plain?copy
  1. #!/bin/bash??
  2. ??
  3. for?i?in?`seq?2000`???
  4. do??
  5. ????./client.out?127.0.0.1?8989??
  6. done??

循環 執行2000次。

第二個shell文件:

[html]?view plain?copy
  1. #!/bin/bash??
  2. ??
  3. ./loop.sh?>?file1?&??
  4. ./loop.sh?>?file2?&??
  5. ./loop.sh?>?file3?&??
  6. ./loop.sh?>?file4?&??
  7. ./loop.sh?>?file5?&??
  8. wait??
開啟5個進程來返問。

執行第二個shell文件

最終,耗時為:

[html]?view plain?copy
  1. real????0m7.589s??
  2. user????0m0.460s??
  3. sys?0m1.944s??

而且五個File文件中,有Hello的行數數都為2000.


下一篇是實現一個簡單小型的web服務器。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/383702.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/383702.shtml
英文地址,請注明出處:http://en.pswp.cn/news/383702.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

TCP第四次揮手為什么要等待2MSL

當客戶端進入TIME-WAIT狀態的時候(也就是第四次揮手的時候)&#xff0c;必須經過時間計數器設置的時間2MSL(最長報文段壽命)后&#xff0c;才能進入關閉狀態&#xff0c;這時為什么呢&#xff1f;&#xff1f;&#xff1f; 這最主要是因為兩個理由&#xff1a; 1、為了保證客戶…

計算機網絡【一】概述+OSI參考模型

網絡概述 局域網:覆蓋范圍小(100m以內)&#xff0c;自己花錢買設備&#xff0c;帶寬固定(10M,100M,1000M)&#xff0c;自己維護&#xff08;接入層交換機直接連接電腦、匯聚層交換機直接連接接入層交換機&#xff09; 廣域網:距離遠&#xff0c;花錢買服務&#xff0c;租帶寬&…

單鏈表逆序的多種方式

https://www.cnblogs.com/eniac12/p/4860642.htmltemplate<class T> void List<T>::Inverse() {if(first NULL) return;LinkNode<T> *p, *prev, *latter; p first->link;   // 當前結點prev NULL;   // 前一結點l…

Linux系統【四】進程間通信-管道

進程間通信&#xff08;IPC Interprocess Communication&#xff09; 進程和進程之間的通信只能通過內核&#xff0c;在內核中提供一塊緩沖區進行通信。內核提供的這種機制叫做IPC 在進程間完成數據傳輸需要借助操作系統提供的特殊方法&#xff0c;如&#xff1a;文件&#xf…

單鏈表各種操作詳解

#include "stdio.h" #include "stdlib.h"#define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0#define MAXSIZE 20 /* 存儲空間初始分配量 */typedef int Status;/* Status是函數的類型,其值是函數結果狀態代碼&#xff0c;如OK等 */ typedef int…

Linux系統【五】進程間通信-共享內存mmap

mmap函數 #include <sys/mman.h> void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);參數&#xff1a; void *addr建立映射區的首地址&#xff0c;由Linux內核指定&#xff0c;所以我們直接傳遞NULL。也就是說雖然這是一個參宿但是并不…

socket編程 -- epoll模型服務端/客戶端通信的實現

https://blog.csdn.net/y396397735/article/details/50680359 本例實現如下功能&#xff1a; 支持多客戶端與一個服務端進行通信&#xff0c;客戶端給服務端發送字符串數據&#xff0c;服務端將字符串中小寫轉為大寫后發送回客戶端&#xff0c;客戶端打印輸出經轉換后的字符串。…

Python3 面向對象程序設計

類的定義 Python使用class關鍵字來定義類 class Car:def infor(self):print("This is a car") car Car() car.infor()內置方法isinstance()來測試一個對象是否為某個類的實例 self參數 類的 所有實例方法都有一個默認的self參數&#xff0c;并且必須是方法的第一…

計算機網絡【二】物理層基礎知識

計算機網絡的性能 速率&#xff1a;連接在計算機網絡上的主機在數字信道上傳送數據位數的速率&#xff0c;也成為data rate 或bit rate&#xff0c;單位是b/s,kb/s,Mb/s,Gb/s。 我們平時所講的寬帶的速度是以字為單位的&#xff0c;但是實際中應用一般顯示的是字節 &#xff0…

Linux網絡編程——tcp并發服務器(多進程)

https://blog.csdn.net/lianghe_work/article/details/46503895一、tcp并發服務器概述一個好的服務器,一般都是并發服務器&#xff08;同一時刻可以響應多個客戶端的請求&#xff09;。并發服務器設計技術一般有&#xff1a;多進程服務器、多線程服務器、I/O復用服務器等。二、…

求序列第K大算法總結

參考博客&#xff1a;傳送門 在上面的博客中介紹了求序列第K大的幾種算法&#xff0c;感覺收益良多&#xff0c;其中最精巧的還是利用快速排序的思想O(n)查詢的算法。仔細學習以后我將其中的幾個實現了一下。 解法 1&#xff1a; 將亂序數組從大到小進行排序然后取出前K大&a…

Linux網絡編程——tcp并發服務器(多線程)

https://blog.csdn.net/lianghe_work/article/details/46504243tcp多線程并發服務器多線程服務器是對多進程服務器的改進&#xff0c;由于多進程服務器在創建進程時要消耗較大的系統資源&#xff0c;所以用線程來取代進程&#xff0c;這樣服務處理程序可以較快的創建。據統計&a…

計算機網絡【三】物理層數據通信

物理層傳輸媒介 導向傳輸媒體&#xff0c;比如光纖和銅線 雙絞線&#xff08;屏蔽雙絞線STP 五屏蔽雙絞線UTP&#xff09;電線扭曲在一起可以降低互相之間的電磁干擾 同軸電纜 (50歐姆的基帶同軸電纜&#xff0c;75歐姆的寬帶同軸電纜) 10M和100M網絡只使用了四根線&#xf…

02_算法分析

02_算法分析 0.1 算法的時間復雜度分析0.1.1 函數漸近增長概念&#xff1a;輸入規模n>2時&#xff0c;算法A1的漸近增長小于算法B1 的漸近增長隨著輸入規模的增大&#xff0c;算法的常數操作可以忽略不計測試二&#xff1a;隨著輸入規模的增大&#xff0c;與最高次項相乘的常…

Linux網絡編程——I/O復用之select詳解

https://blog.csdn.net/lianghe_work/article/details/46506143一、I/O復用概述I/O復用概念&#xff1a;解決進程或線程阻塞到某個 I/O 系統調用而出現的技術&#xff0c;使進程不阻塞于某個特定的 I/O 系統調I/O復用使用的場合&#xff1a;1.當客戶處理多個描述符&#xff08;…

Linux多進程拷貝文件

學習了mmap以后&#xff0c;實現一個簡單的小程序&#xff0c;進行多個進程對一個文件進行拷貝。 Linux mmap共享內存學習可以參考我的另一篇博客&#xff1a;傳送門 實現思想 我們可以將原來的文件利用mmap分成多個段分別進行傳輸。 實現代碼 #include<stdio.h> #…

斐波那契查找(Fibonacci Search)和折半查找

兩個查找算法都是針對有序數組進行查找&#xff0c;不同點在于分界點的取值不同。 算法介紹 折半查找很簡單&#xff0c;每次與當前區間的中點進行比較&#xff0c;然后決定查找前一部分還是后一部分。 Fibonacci查找利用了Fibonacci序列每一項等于前兩項和的特點進行劃分&a…

Linux網絡編程——tcp并發服務器(I/O復用之select)

https://blog.csdn.net/lianghe_work/article/details/46519633與多線程、多進程相比&#xff0c;I/O復用最大的優勢是系統開銷小&#xff0c;系統不需要建立新的進程或者線程&#xff0c;也不必維護這些線程和進程。代碼示例&#xff1a;#include <stdio.h> #include &l…

操作系統【二】死鎖問題以及處理方法

死鎖的概念 死鎖&#xff1a;在并發環境下&#xff0c;個進程因為競爭資源而造成的一種互相等待對方手里的資源&#xff0c;導致各進程都阻塞&#xff0c;無法向前推進的現象。 區別&#xff1a; 饑餓&#xff1a;由于長期得不到想要的資源進程無法向前推進的現象。死循環&a…