阻塞和非阻塞套接字一次可以发送多大的数据量
2016-01-18 11:14
323 查看
我们应该知道无论是阻塞还是非阻塞,其调用send来发送数据的实质是将应用程序缓冲区的数据拷贝到socket缓冲区中,然后协议栈对这些数据进行发送,也就说send就是拷贝。因此我之前的理解是:对于套接字发送数据(阻塞和非阻塞),其一次发送的数据量不能大于socket缓冲区的大小。
在当前项目中使用的是非阻塞套接字,并且将socket的发送缓冲区大小设置为1M,以防止较大量的数据发送。现在遇到了一个数据包的大小大于1M的情况,这总不能一直来扩大socket的发送缓冲区吧,担心会使数据拷贝的时间大大增大。因此参照了darwin的数据发送,发现其发送数据时没有考虑数据量与socket发送缓冲区的大小,并且socket的发送缓冲区被设置为96K,但是可以调用send函数来发送数据量为几M的数据。这是为什么?
难道应该是这样:阻塞套接字一次发送的数据量不能大于socket缓冲区的大小,而非阻塞可以。
伟人毛主席说过,没有调查就没有发言权。对于程序员,能用代码说的事就不要猜测,下面写了一个小的程序来测试阻塞和非阻塞套接字一次可以发送的数据量有多大:
由结果可知。对于非阻塞和阻塞套接字,其一次可以发送的数据的大小均不受socket发送缓冲区大小的限制。至于非阻塞下面的10035错误代码,只是表明当前缓冲区满而已,只需在合适的时候再次调用send进行发送即可。如果是这样的话,那么socket的使用就简单多了,看来send里面还是封装了不少的东西,期待看到linux下的源码实现。
如有错误,欢迎指教。
在当前项目中使用的是非阻塞套接字,并且将socket的发送缓冲区大小设置为1M,以防止较大量的数据发送。现在遇到了一个数据包的大小大于1M的情况,这总不能一直来扩大socket的发送缓冲区吧,担心会使数据拷贝的时间大大增大。因此参照了darwin的数据发送,发现其发送数据时没有考虑数据量与socket发送缓冲区的大小,并且socket的发送缓冲区被设置为96K,但是可以调用send函数来发送数据量为几M的数据。这是为什么?
难道应该是这样:阻塞套接字一次发送的数据量不能大于socket缓冲区的大小,而非阻塞可以。
伟人毛主席说过,没有调查就没有发言权。对于程序员,能用代码说的事就不要猜测,下面写了一个小的程序来测试阻塞和非阻塞套接字一次可以发送的数据量有多大:
//建立一个win32控制台应用程序 #include "stdafx.h" #include<winsock2.h> #pragma comment(lib,"Ws2_32.lib") #include<iostream> using std::cout; using std::endl; int _tmain(int argc, _TCHAR* argv[]) { WORD wVersionRequested; WSADATA wsaData={0}; int err; wVersionRequested = MAKEWORD( 2, 2 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return -1; // 返回值为零的时候是表示成功申请WSAStartup } cout<<"初始化成功"<<endl; SOCKET sd=socket(AF_INET,SOCK_STREAM,0); if(sd==INVALID_SOCKET) { cout<<"创建套接字失败\n"<<endl; WSACleanup(); return 0; } cout<<"创建socket成功"<<endl; int nSendBuf=1024*1024;//设置发送缓冲区的大小1M if(setsockopt(sd,SOL_SOCKET,SO_SNDBUF,(const char*)&nSendBuf,sizeof(int))==SOCKET_ERROR) { cout<<"设置发送缓冲区失败"<<endl; closesocket(sd); WSACleanup(); } cout<<"设置发送缓冲区成功"<<endl; sockaddr_in saServer; saServer.sin_family=AF_INET; saServer.sin_addr.s_addr=inet_addr("192.168.4.199"); saServer.sin_port=htons(10000); if(connect(sd,(sockaddr*)&saServer,sizeof(sockaddr_in))==SOCKET_ERROR)//在此使用阻塞套接字连接 { cout<<"连接服务器失败"<<endl; closesocket(sd); WSACleanup(); return 0; } cout<<"连接服务器成功"<<endl; cout<<"阻塞套接字测试"<<endl;; char *SendBuf=new char[1024*1024*2]; int i=0; int SendLen; while(i++<10)//测试10次 { SendLen=send(sd,SendBuf,1024*1024*2,0); if(SendLen==SOCKET_ERROR) { cout<<"错误代码"<<WSAGetLastError()<<endl; } else { cout<<"发送数据长度为"<<SendLen<<endl; } } unsigned long ul = 1; if(ioctlsocket(sd, FIONBIO,&ul)==SOCKET_ERROR) { cout<<"设置非阻塞模式失败"<<endl; closesocket(sd); WSACleanup(); return 0; } cout<<"设置非阻塞模式成功"<<endl; cout<<"非阻塞套接字测试"<<endl; i=0; while(i++<10)//测试10次 { SendLen=send(sd,SendBuf,1024*1024*2,0); if(SendLen==SOCKET_ERROR) { cout<<"错误代码"<<WSAGetLastError()<<endl; } else { cout<<"发送数据长度为"<<SendLen<<endl; } } closesocket(sd); WSACleanup(); delete[] SendBuf; system("pause"); return 0; }
代码很简单,创建了一个指定发送缓冲区大小为1M的socket,并分别测试其在阻塞和非阻塞模式下发送2M的数据的能力。这仅仅是一个客户端程序,服务器程序使用的是测试工具TCP/UDP debug,其运行结果截图如下:
由结果可知。对于非阻塞和阻塞套接字,其一次可以发送的数据的大小均不受socket发送缓冲区大小的限制。至于非阻塞下面的10035错误代码,只是表明当前缓冲区满而已,只需在合适的时候再次调用send进行发送即可。如果是这样的话,那么socket的使用就简单多了,看来send里面还是封装了不少的东西,期待看到linux下的源码实现。
如有错误,欢迎指教。
相关文章推荐
- 1、JMX的Hello World
- hdu 1160 FatMouse's Speed dp
- Android APP 应用分析
- Fragment的生命周期之我见
- 【第十二章】零配置 之 12.1 概述 ——跟我学spring3
- Android Design Support Library——TextInputLayout
- 利众讲故事:攻下隔壁女生路由器后,我都做了些什么
- 世界首富的经验:2016程序员必看的8大成功法则
- 实现点击音乐文件跳转到音乐播放器并自动播放音乐
- Java学习笔记(69)---------Lock
- 手把手教你画一个 逼格满满圆形水波纹loadingview Android
- Java反射机制实践
- python 详解re模块
- 引用计数法的循环引用问题
- 手把手教你画一个 逼格满满圆形水波纹loadingview Android
- 网络安全-跨站脚本攻击XSS(Cross-Site Scripting)
- 【zz】matlab 均值方差
- AUTOCAD参数约束功能
- 打开开源项目总得.md文件
- 破解 AD_CM#3