socket之recv和send函數


一、send函數

函數原型:int send( SOCKET s,char *buf,int len,int flags );

功能:不論是客戶還是服務器應用程序都用send函數來向TCP連接的另一端發送數據。客戶程序一般用send函數向服務器發送請求,而服務器則通常用send函數來向客戶程序發送應答。

參數一:指定發送端套接字描述符;

參數二:存放應用程序要發送數據的緩沖區;

參數三:實際要發送的數據的字節數;

參數四:一般置為0。


同步Socket的send函數的執行流程,當調用該函數時,send先比較待發送數據的長度len和套接字s的發送緩沖的長度(因為待發送數據是要copy到套接字s的發送緩沖區的,注意並不是send把s的發送緩沖中的數據傳到連接的另一端的,而是協議傳的,send僅僅是把buf中的數據copy到s的發送緩沖區的剩余空間里):

1.如果len大於s的發送緩沖區的長度,該函數返回SOCKET_ERROR;

2.如果len小於或者等於s的發送緩沖區的長度,那么send先檢查協議是否正在發送s的發送緩沖中的數據,如果是就等待協議把數據發送完,如果協議還沒有開始發送s的發送緩沖中的數據或者s的發送緩沖中沒有數據,那么 send就比較s的發送緩沖區的剩余空間和len:

      (i)如果len大於剩余空間大小send就一直等待協議把s的發送緩沖中的數據發送完;

      (ii)如果len小於剩余空間大小send就僅僅把buf中的數據copy到剩余空間里。

3.如果send函數copy數據成功,就返回實際copy的字節數,如果send在copy數據時出現錯誤,那么send就返回SOCKET_ERROR;如果send在等待協議傳送數據時網絡斷開的話,那么send函數也返回SOCKET_ERROR。

注意:send函數把buf中的數據成功copy到s的發送緩沖的剩余空間里后它就返回了,但是此時這些數據並不一定馬上被傳到連接的另一端。如果協議在后續的傳送過程中出現網絡錯誤的話,那么下一個Socket函數就會返回SOCKET_ERROR。(每一個除send外的Socket函數在執行的最開始總要先等待套接字的發送緩沖中的數據被協議傳送完畢才能繼續,如果在等待時出現網絡錯誤,那么該Socket函數就返回 SOCKET_ERROR)

二、recv函數

函數原型:int recv( SOCKET s, char *buf, int  len, int flags)

功能:不論是客戶還是服務器應用程序都用recv函數從TCP連接的另一端接收數據。

參數一:指定接收端套接字描述符;

參數二:指明一個緩沖區,該緩沖區用來存放recv函數接收到的數據;

參數三:指明buf的長度;

參數四 :一般置為0。


同步Socket的recv函數的執行流程:當應用程序調用recv函數時,recv先等待s的發送緩沖中的數據被協議傳送完畢,

如果協議在傳送s的發送緩沖中的數據時出現網絡錯誤,那么recv函數返回SOCKET_ERROR;

如果s的發送緩沖中沒有數據或者數據被協議成功發送完畢后,recv先檢查套接字s的接收緩沖區,如果s接收緩沖區中沒有數據或者協議正在接收數據,那么recv就一直
等待,直到協議把數據接收完畢;

當協議把數據接收完畢,recv函數就把s的接收緩沖中的數據copy到buf中(注意協議接收到的數據可能大於buf的長度,所以在這種情況下要調用幾次recv函數才能把s的接收緩沖中的數據copy完。recv函數僅僅是copy數據,真正的接收數據是協議來完成的),recv函數返回其實際copy的字節數;

如果recv在copy時出錯,那么它返回SOCKET_ERROR;如果recv函數在等待協議接收數據時網絡中斷了,那么它返回0。


三、簡單示例

通過send函數發送get請求到web服務器,利用recv函數接受web服務器返回的數據。

[cpp]  view plain  copy
  1. #include<stdio.h>  
  2. #include<winsock2.h>  
  3. #include<windows.h>  
  4. #pragma comment(lib, "ws2_32.lib")  
  5.   
  6. using namespace std;  
  7.   
  8. typedef struct{  
  9.     char line[256];  
  10.     char head[256];  
  11.     //char body[256];  
  12. }message;  
  13.   
  14. int main()  
  15. {  
  16.     int num;  
  17.       
  18.     SOCKET s;  
  19.     WSADATA wsa;  
  20.     struct sockaddr_in serv;  
  21.     message req;  
  22.       
  23.     char sndBuf[1024], rcvBuf[2048];  
  24.   
  25.     WSAStartup(MAKEWORD(2, 1), &wsa);  
  26.   
  27.   
  28.     if ((s = socket(AF_INET, SOCK_STREAM, 0))<0)  
  29.     {  
  30.         perror("socket error!");  
  31.         exit(1);  
  32.     }  
  33.   
  34.     memset(&serv, 0, sizeof(serv));  
  35.     serv.sin_family = AF_INET;  
  36.     serv.sin_port = htons(80);  
  37.     serv.sin_addr.S_un.S_addr = inet_addr("115.239.210.26");  
  38.   
  39.     //BING 70.37.92.127  
  40.     //BAIDU 115.239.210.26  
  41.     //baidu api 180.149.132.118  
  42.     //google 74.125.31.99  
  43.     //sina  59.175.132.113  
  44.     //163   222.243.110.164  
  45.     //taobao   218.75.155.151  
  46.     //jd    116.211.94.1  
  47.   
  48.     if ((connect(s, (struct sockaddr *)&serv, sizeof(serv)))<0)  
  49.     {  
  50.         perror("connet error!");  
  51.         exit(1);  
  52.     }  
  53.   
  54.     memset(sndBuf, 0, 1024);  
  55.     memset(rcvBuf, 0, 2048);  
  56.   
  57.     strcpy(req.line, "GET /index.html  HTTP/1.0\r\n");  
  58.     strcat(sndBuf, req.line);  
  59.     strcpy(req.head, "\r\n");  
  60.     strcat(sndBuf, req.head);  
  61.       
  62.     puts(sndBuf);  
  63.     
  64.     if ((num = send(s,sndBuf,1024, 0))<0)  
  65.    {  
  66.         perror("send error!");  
  67.         exit(1);  
  68.     }  
  69.       
  70.     puts("send success!\n");  
  71.   
  72.     do{  
  73.   
  74.         if ((num = recv(s, rcvBuf, 2048, 0))<0)  
  75.         {  
  76.             perror("recv error!");  
  77.             exit(1);  
  78.         }  
  79.         else if (num>0)  
  80.         {  
  81.             printf("%s", rcvBuf);  
  82.             memset(rcvBuf, 0, 2048);  
  83.         }  
  84.     } while (num>0);  
  85.       
  86.     puts("\nread success!\n");  
  87.   
  88.     closesocket(s);  
  89.       
  90.     system("pause");  
  91.     WSACleanup();  
  92.       
  93.     return 0;  
  94. }  


原帖地址:http://blog.csdn.net/lanzhihui_10086/article/details/40681617


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com