socket之send與傳送緩衝區大小的關係
自己做了個測試,伺服器只起socket在偵聽,不recv, 也不send.
//ubuntu10.04 32bit #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> int main(void) { int fd; struct sockaddr_in addr; fd = socket(AF_INET, SOCK_STREAM, 0); addr.sin_family = AF_INET; addr.sin_port = htons(103); addr.sin_addr.s_addr = htonl(INADDR_ANY); bind(fd, (struct sockaddr *)&addr, sizeof(addr)); listen(fd,5); }
客戶端,將傳送緩衝區大小設定成2k,然後一次傳送3k的資料。
//ubuntu10.04 32bit #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <arpa/inet.h> int main() { int fd,ret,tmp,sendlen; struct sockaddr_in addr; char *buf; int sendBufLen = 1024*2; socklen_t optlen = sizeof(int); buf = (char *)malloc(1024 * 3); fd = socket(AF_INET, SOCK_STREAM,0 ); setsockopt(fd,SOL_SOCKET, SO_SNDBUF,(const char*)&sendBufLen, sizeof(int)); getsockopt(fd,SOL_SOCKET, SO_SNDBUF,(int *)&tmp, &optlen); printf("send_tmp=%d,optlen=%d\n",tmp,(int)optlen); //設定傳送緩衝區2048 getsockopt(fd,SOL_SOCKET, SO_RCVBUF,(int *)&tmp, &optlen); printf("recv_tmp=%d,optlen=%d\n",tmp,(int)optlen); addr.sin_family = AF_INET; addr.sin_port = htons(103); addr.sin_addr.s_addr = inet_addr("222.111.112.204"); //填上自己的IP ret = connect (fd, (struct sockaddr *)&addr, sizeof(addr)); printf("connect return %d\n",ret); getchar(); if (ret >= 0) sendlen = send(fd,buf,1024*3,0); printf("sendlen=%d\n",sendlen); //此處返回3072 getchar(); return 0; }
互動報文
從這裡看出當傳送長度大於緩衝區大小時,是分次傳送,三次加起來 1448 + 1448 + 176 = 3072
在windows下,做同樣的測試
抓取報文// xp vc6.0 32bit #include <stdio.h> #include <winsock2.h> #include <iostream.h> #pragma comment (lib,"ws2_32") void main() { int len,optval,optlen,iResult; SOCKADDR_IN clientService;// 地址 SOCKET ConnectSocket;// socket WSADATA wsaData;// 庫 unsigned char buf[1024*3]; //初始化socket庫, 儲存ws2_32.dll已經載入 iResult = WSAStartup(MAKEWORD(2,2), &wsaData); if (iResult != NO_ERROR) printf("Error at WSAStartup()\n"); // 建立socket ConnectSocket = socket(AF_INET, // IPv4 SOCK_STREAM, // 順序的、可靠的、基於連線的、雙向的資料流通訊 IPPROTO_TCP // 使用TCP協議 /*0*/); if (ConnectSocket == INVALID_SOCKET) { printf("Error at socket(): %d\n", WSAGetLastError()); WSACleanup(); return ; } optlen = sizeof(optval); getsockopt(ConnectSocket, SOL_SOCKET, SO_SNDBUF, (char*)&optval, &optlen); printf("send buf len is %d\n",optval); //預設傳送緩衝區8k getsockopt(ConnectSocket, SOL_SOCKET, SO_RCVBUF, (char*)&optval, &optlen); printf("Recv buf len is %d\n",optval); //預設接收緩衝區8k optval = 1024 * 2; setsockopt(ConnectSocket, SOL_SOCKET, SO_SNDBUF, (char*)&optval, optlen); getsockopt(ConnectSocket, SOL_SOCKET, SO_SNDBUF, (char*)&optval, &optlen); printf("send buf len change to %d\n",optval); // 設定服務端的通訊協議、IP地址、埠 clientService.sin_family = AF_INET; clientService.sin_addr.s_addr = inet_addr( "222.111.112.204" ); clientService.sin_port = htons( 103 ); // 連線到服務端 if ( connect( ConnectSocket, // socket (SOCKADDR*) &clientService, // 地址 sizeof(clientService) // 地址的大小 ) == SOCKET_ERROR) { printf( "Failed to connect(%d)\n",WSAGetLastError() ); WSACleanup(); return ; } len = send(ConnectSocket, (char*)buf, 1024*3, 0); printf("send length is %d\n",len); //這裡同樣直接返回3072 system("pause"); return; }
分三次傳送1460+1460+152 = 3072
上面都是阻塞的傳送,對於socket是非阻塞的話,做同樣的測試
//ubuntu10.04 32bit
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
int main()
{
int fd,ret,tmp,sendlen,flags,fd_num;
fd_set rset,wset;
struct timeval tval;
struct sockaddr_in addr;
char *buf;
int sendBufLen = 1024*2;
socklen_t optlen = sizeof(int);
buf = (char *)malloc(1024 * 3);
fd = socket(AF_INET, SOCK_STREAM,0 );
setsockopt(fd,SOL_SOCKET, SO_SNDBUF,(const char*)&sendBufLen, sizeof(int));
getsockopt(fd,SOL_SOCKET, SO_SNDBUF,(int *)&tmp, &optlen);
printf("send_tmp=%d,optlen=%d\n",tmp,(int)optlen);
getsockopt(fd,SOL_SOCKET, SO_RCVBUF,(int *)&tmp, &optlen);
printf("recv_tmp=%d,optlen=%d\n",tmp,(int)optlen);
flags = fcntl(fd,F_GETFL,0);
fcntl(fd,F_SETFL,flags|O_NONBLOCK);
addr.sin_family = AF_INET;
addr.sin_port = htons(103);
addr.sin_addr.s_addr = inet_addr("222.111.112.204");
ret = connect (fd, (struct sockaddr *)&addr, sizeof(addr));
if ((ret < 0) && (errno == EINPROGRESS))
{
FD_ZERO(&rset);
FD_SET(fd,&rset);
wset = rset;
tval.tv_sec = 3;
tval.tv_usec = 0;
if ( -1 == (fd_num = select(fd+1, &rset, &wset, NULL, &tval)))
{
perror("select error");
exit(0);
}
else
{
if ((fd_num == 1) && FD_ISSET(fd, &wset)) //connect only can be write
{
printf("connect OK!\n");
}
else
{
perror("state error");
exit(0);
}
}
}
if (-1 ==(sendlen = send(fd,buf,1024*3,0)))
{
perror("send error");
}
else
{
printf("sendlen=%d\n",sendlen); //直接返回3072
}
return 0;
}
和blocking socket表現是一樣的,一次send,協議棧分三幀傳送。
//xp vc6.0 32bit
#include <stdio.h>
#include <winsock2.h>
#include <iostream.h>
#pragma comment (lib,"ws2_32")
void main()
{
int len,optval,optlen,iResult,fd_num,on=1;
SOCKADDR_IN clientService;// 地址
SOCKET ConnectSocket;// socket
WSADATA wsaData;// 庫
unsigned char buf[1024*3];//
fd_set rset,wset;
struct timeval tval;
//初始化socket庫, 儲存ws2_32.dll已經載入
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR)
printf("Error at WSAStartup()\n");
// 建立socket
ConnectSocket = socket(AF_INET, // IPv4
SOCK_STREAM, // 順序的、可靠的、基於連線的、雙向的資料流通訊
IPPROTO_TCP // 使用TCP協議
/*0*/);
if (ConnectSocket == INVALID_SOCKET)
{
printf("Error at socket(): %d\n", WSAGetLastError());
WSACleanup();
return ;
}
if(0 == ioctlsocket(ConnectSocket, FIONBIO, (unsigned long *)&on))
{
printf("socket non-blocking set success!\n");
}
optlen = sizeof(optval);
getsockopt(ConnectSocket, SOL_SOCKET, SO_SNDBUF, (char*)&optval, &optlen);
printf("send buf len is %d\n",optval);
getsockopt(ConnectSocket, SOL_SOCKET, SO_RCVBUF, (char*)&optval, &optlen);
printf("Recv buf len is %d\n",optval);
optval = 1024 * 2;
setsockopt(ConnectSocket, SOL_SOCKET, SO_SNDBUF, (char*)&optval, optlen);
getsockopt(ConnectSocket, SOL_SOCKET, SO_SNDBUF, (char*)&optval, &optlen);
printf("send buf len change to %d\n",optval);
// 設定服務端的通訊協議、IP地址、埠
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr( "222.111.112.204" );
clientService.sin_port = htons( 103 );
// 連線到服務端
if ( connect(
ConnectSocket, // socket
(SOCKADDR*) &clientService, // 地址
sizeof(clientService) // 地址的大小
) == SOCKET_ERROR)
{
if ( WSAEWOULDBLOCK == WSAGetLastError() )
{
FD_ZERO(&rset);
FD_SET(ConnectSocket,&rset);
wset = rset;
tval.tv_sec = 3;
tval.tv_usec = 0;
if (SOCKET_ERROR == (fd_num = select(ConnectSocket+1, &rset, &wset, NULL, &tval)))
{
printf( "select Failed (%d)\n",WSAGetLastError() );
WSACleanup();
return ;
}
else
{
if ((fd_num == 1) && FD_ISSET(ConnectSocket, &wset)) //connect成功後,只能可寫,不能可讀可寫
{
printf("connect OK!\n");
}
else
{
printf( "connect Failed (%d)\n",WSAGetLastError() );
WSACleanup();
return ;
}
}
}
else
{
printf( "Failed to connect(%d)\n",WSAGetLastError() );
WSACleanup();
return ;
}
}
if (SOCKET_ERROR == (len=send(ConnectSocket, (char*)buf, 1024*3, 0)))
{
printf("send error %d\n", WSAGetLastError());
}
else
{
printf("send length is %d\n",len); //直接返回3072
}
system("pause");
return;
}
可見,當send的資料長度大於socket的緩衝區長度時,不管是windows還是linux,send都會分幀傳送。
相關推薦
socket之send與傳送緩衝區大小的關係
自己做了個測試,伺服器只起socket在偵聽,不recv, 也不send. //ubuntu10.04 32bit #include <stdio.h> #include <sys/types.h> #include <sys/socke
tcp協議系列文章(7):send()的資料大小與可用的傳送緩衝區大小的關係
筆者這裡要指出的是,man send 手冊上說的或許與send()的版本有關。詳細的,可以檢視筆者的另一篇部落格,上面有就send()的行為的詳細說法。 下面的部落格內容,其實驗證的方法與驗證的目的並不相同!!!請讀者注意!!! 自己做了個測試,伺服器只起s
C++ Socket程式設計(二) send與recv 緩衝區與阻塞
socket緩衝區 每一個socket在被建立之後,系統都會給它分配兩個緩衝區,即輸入緩衝區和輸出緩衝區。 send函式並不是直接將資料傳輸到網路中,而是負責將資料寫入輸出緩衝區,資料從輸出緩衝區傳送到目標主機是由TCP協議完成的。資料寫入到輸出緩衝區之
六、資料庫之 表與表之間的關係
表1 foreign key 表2 則表1的多條記錄對應表2的一條記錄,即多對一 利用foreign key的原理我們可以製作兩張表的多對多,一對一關係 多對多: 表1的多條記錄可以對應表2的一條記錄 表2的多條記錄也可以對應表1的一條
(多圖) 超強整理!PCB設計之電流與線寬的關係
源:(多圖) 超強整理!PCB設計之電流與線寬的關係 http://www.51hei.com/bbs/dpj-39134-1.html 關於PCB線寬和電流的經驗公式,關係表和軟體網上都很多,本文把網上的整理了一下,旨在給廣大工程師在設計PCB板的時候提供方便。 以下總結了
mysql學習【第6篇】:資料庫之表與表之間的關係 資料庫之 表與表之間的關係
資料庫之 表與表之間的關係 表1 foreign key 表2 則表1的多條記錄對應表2的一條記錄,即多對一
超強整理!PCB設計之電流與線寬的關係
超強整理!PCB設計之電流與線寬的關係 關於pcb線寬和電流的經驗公式,關係表和軟體網上都很多,本文把網上的整理了一下,旨在給廣大工程師在設計PCB板的時候提供方便。 以下總結了八種電流與線寬的關係公式,表和計算公式,雖然各不相同(大體
微信公眾號開發之接收與傳送訊息
說明:該篇部落格是博主一字一碼編寫的,實屬不易,請尊重原創,謝謝大家! 在上一篇部落格中已經驗證了伺服器有效性:https://blog.csdn.net/qq_41782425/article/details/85321424 一丶概論 公眾號接收與傳送訊息 驗證
Socket中send方法傳送結構體和recv接受結構體
Socket中的send函式可以傳送字串,但不能直接傳送結構體,因此在傳送端先把結構體轉成字串,然後用send傳送,在接收端recv字串,再轉換成原先的結構體,這個就是解決問題的主要思路,實現中要注意的問題在下文闡述。 為了客戶端之間能夠互相通訊,實現私聊
資料庫之 表與表之間的關係
表1 foreign key 表2 則表1的多條記錄對應表2的一條記錄,即多對一 利用foreign key的原理我們可以製作兩張表的多對多,一對一關係 多對多: 表1的多條記錄可以對應表2的一條記錄 表2的多條記錄也可以對應表1的一條記錄 一對一:
socket之send和recv原理剖析
談到網路socket程式設計, 我們不得不提兩個基本也很重要的函式:send和recv. 對socket程式設計理解不深的童鞋容易產生這樣一個錯誤的認識: send函式是用來發送資料, 而recv函式是用來接收資料的, 其實, 這種觀點是稍微有點偏頗的, 掩蓋了本質。
boost庫之socket 非阻塞/緩衝區大小等屬性設定
asio socket 非阻塞/緩衝區大小等屬性設定ip::tcp::socket m_socket //設定阻塞與非阻塞void SetNoBlock(bool bNoBlock){ if(bNoBlock) { boost::asio::socket_base::by
面試之經典問題-傳送/接受視窗與快取的關係
1,tcp傳輸報文段,傳送視窗與快取的關係??? 2,普通意義上的,TCP傳輸報文段的時候會產生稍帶確認嗎??? 3,接受方收到位元組確認不是按順序的,那麼對這些東西已經收到的確認號如何處理???
設定SOCKET的傳送與接收緩衝區
主 題: 淺析:setsockopt()改善程式的健壯性 作 者: gdy119 (夜風微涼) 不斷的收到coolmei25 (梅生)的答謝,我都不好意思了(我都沒幫到他),下面寫出我在網路程式設計中的一點心得體會,希望對他(^_^也對大家)有幫助:1. 如果在已經處於
Socket、send/recv的迴圈傳送和接收、緩衝區、阻塞
這篇文章略作刪減後轉過來了。主要有以下幾點值得自己注意的: (1)剛開頭對套接字的理解。 (2)緩衝區的理解。 其他部分有時間重新整理。 套接字的概念及分類 在網路中,要全域性的標識一個參與通訊的程序,需要三元組:協議,IP地址以及埠號。要描述兩個應用
Java Socket 實現HTTP與HTTPS協議傳送POST/GET請求
JAVA Socket 實現HTTP與HTTPS客戶端傳送POST與GET方式請求 哇,一看標題怎麼這麼長啊,其實意思很簡單,哥討厭用HTTP Client做POST與GET提交覺得那個畢竟是別人寫得AP
python摸爬滾打之day17----類與類之間的關係
1、類與類之間的聯絡 1.1 依賴關係 類A中使用了類B, 類B作為引數傳進類A的方法中被使用. 這種關係中類與類之間的聯絡是最輕的. 1 class Elephant: 2 3 def open(self,ele):
1015 - 計算幾何之點與多邊形的關係 - Points Within(ZOJ1081)
傳送門 分析 射線法 雖然這個射線法有很多需要特判的情況,但總的來說還是蠻好用的 判斷點與多邊形的關係,若使用射線法,就是說從這個點往右做一條與 x 軸平行的射線,看它與多邊形相交了幾次 若相交了偶數次,則不在多邊形內部(相當於從這個多邊形中穿過去,沒有留在
1015 - 計算幾何之直線與直線的關係 - Intersecting Lines(POJ1269)
傳送門 題意 給你兩條直線 若其相交則輸出 交點的座標 若其平行則輸出 NONE 若其重合則輸出 LINE 分析 比較基礎的計算幾何,就是考向量的使用 判斷兩條直線是否平行,就是看其叉積是否為
1016 - 計算幾何之點與直線的關係 - TOYS(POJ 2318)
傳送門 題意 給你一個這樣的圖 然後隨機給你 m 個點,問落在每一個區域內的點有多少個 分析 入門題入門題 依舊是利用叉積,叉積太強了! 二分尋找並判斷 gsj太厲害了,簡直每次我演算法