一、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服務器返回的數據。
- #include<stdio.h>
- #include<winsock2.h>
- #include<windows.h>
- #pragma comment(lib, "ws2_32.lib")
- using namespace std;
- typedef struct{
- char line[256];
- char head[256];
- //char body[256];
- }message;
- int main()
- {
- int num;
- SOCKET s;
- WSADATA wsa;
- struct sockaddr_in serv;
- message req;
- char sndBuf[1024], rcvBuf[2048];
- WSAStartup(MAKEWORD(2, 1), &wsa);
- if ((s = socket(AF_INET, SOCK_STREAM, 0))<0)
- {
- perror("socket error!");
- exit(1);
- }
- memset(&serv, 0, sizeof(serv));
- serv.sin_family = AF_INET;
- serv.sin_port = htons(80);
- serv.sin_addr.S_un.S_addr = inet_addr("115.239.210.26");
- //BING 70.37.92.127
- //BAIDU 115.239.210.26
- //baidu api 180.149.132.118
- //google 74.125.31.99
- //sina 59.175.132.113
- //163 222.243.110.164
- //taobao 218.75.155.151
- //jd 116.211.94.1
- if ((connect(s, (struct sockaddr *)&serv, sizeof(serv)))<0)
- {
- perror("connet error!");
- exit(1);
- }
- memset(sndBuf, 0, 1024);
- memset(rcvBuf, 0, 2048);
- strcpy(req.line, "GET /index.html HTTP/1.0\r\n");
- strcat(sndBuf, req.line);
- strcpy(req.head, "\r\n");
- strcat(sndBuf, req.head);
- puts(sndBuf);
- if ((num = send(s,sndBuf,1024, 0))<0)
- {
- perror("send error!");
- exit(1);
- }
- puts("send success!\n");
- do{
- if ((num = recv(s, rcvBuf, 2048, 0))<0)
- {
- perror("recv error!");
- exit(1);
- }
- else if (num>0)
- {
- printf("%s", rcvBuf);
- memset(rcvBuf, 0, 2048);
- }
- } while (num>0);
- puts("\nread success!\n");
- closesocket(s);
- system("pause");
- WSACleanup();
- return 0;
- }
原帖地址:http://blog.csdn.net/lanzhihui_10086/article/details/40681617