关于Socket发送大数据包

弦苦 2009-05-22 02:49:03
int sendCount = 0; // 已经发送的字节数
int left_len = len; // 剩余的字节数
int Times=0; // 发送次数
do{
sendCount = this->Send(sendBuffer + len-left_len, left_len, 0);// CAsyncSocket::Send()
left_len -= sendCount;
}while(left_len > 0)
请问发送大数据包时,比如100M或更大,以上代码在逻辑上好像没问题,但在实际通信中有没有问题呢?
我看到有些代码
在do中添加
Times++;
if(left_len > 0)
::Sleep(200);
在while中控制次数,比如Times<5.
请问这是干什么?
...全文
1221 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
ZOthello 2009-05-24
  • 打赏
  • 举报
回复
个人觉得连接断了就不用再发了,除非它再次请求发送。TCP可以保证无差错的连接,不用管什么断点续传吧~~
弦苦 2009-05-24
  • 打赏
  • 举报
回复
谢谢各位的回复。
(1)year2002提到了缓冲区的问题。
Socket默认的缓冲区大小是8KB,请问大数据是不是分批传送?比如要传送100KB的数据过去,代码如下:
int len = 100*1024; // 发送100KB
LPBYTE sendBuffer = new BYTE[len];
int sendCount = 0; // 已经发送的字节数
int left_len = len; // 剩余的字节数
do{
sendCount = this->Send(sendBuffer + len-left_len, left_len, 0);// CAsyncSocket::Send()
left_len -= sendCount;
}while(left_len > 0)
我们知道TCP建立连接之后,如果不断开或者不出现异常,就一直连接。
下面是MSDN上对Send返回值的说明:
If no error occurs, Send returns the total number of characters sent. (Note that this can be less than the number indicated by nBufLen.) Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling GetLastError.
WSAENETDOWN The Windows Sockets implementation detected that the network subsystem failed.(Windows套接口实现检测到网络子系统失效)
WSAENOTCONN The socket is not connected.(套接口未被连接)
现假设不断开无异常,请问上面的while循环中,CAsyncSocket::Send是不是前12次发送8KB,第13次发送4KB呢?
“对方可以慢慢收,但是你没有慢慢发”,请问我给while循环中加一个Sleep,是不是就可以慢慢发了?
(2)blackcat242和hsuhuasu都提到要考虑返回错误码情况。
<1>断开,比如接收方突然关闭了应用程序,那么Send返回WSAENOTCONN,然后是不是要break。
<2>没有断开,而出现异常的情况,又要怎么处理呢?比如接收了一部分,然后异常,然后过一会有正常了,后面是不是涉 及到所谓断点续传的问题?请问又该如何处理呢?
  • 打赏
  • 举报
回复
也不是说就是发送端要慢慢发,而是发送要根据对方的接受能力来发,比如windows下SOCKET的几种工作模式就是为了解决这些问题的,当然其他平台下都有相应的解决方案。
比如发送缓冲区满了,你就可以等待发送缓冲区的可写事件来触发发送函数,尽量用SOCKET的消息或者事件模式,而不是用SLEEP
弦苦 2009-05-24
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 w_wsh76 的回复:]
没有错,如果接收端是比较正常的话,建议一次发送8000个字节,留点空余可以自己加一些校验.如果接收端不是正常接收,那就是要先判断每次的发送结果再加尝试次数了.
[/Quote]
int len = 100*1024; // 发送100KB
LPBYTE sendBuffer = new BYTE[len];
int sendCount = 0; // 已经发送的字节数
int left_len = len; // 剩余的字节数
do{
sendCount = this->Send(sendBuffer + len-left_len, left_len, 0);// CAsyncSocket::Send()

if(sendCount != SOCKET_ERROR)
{
left_len -= sendCount;
}
else
{
// 中文显示出错信息
LPVOID lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
0, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 默认语言
(LPTSTR)&lpMsgBuf, 0, NULL);
// 显示
::MessageBox(0,(LPCTSTR)lpMsgBuf,_T("GetLastError"),MB_OK|MB_ICONINFORMATION );
// 释放内存
::LocalFree( lpMsgBuf );
// 退出while循环
break;
}

if(left_len > 0)
::Sleep(200); // 慢发送
}while(left_len > 0)
delete sendBuffer;

当然相应我接收端先读取文件长度,然后要做读状态控制。
以上代码中就不加次数控制了,直接以剩余字节数作为控制变量。
正在测试中……
goodname 2009-05-24
  • 打赏
  • 举报
回复
如果send发送的字节数<你给他的字节数,那么可能底层缓冲区满了。
你最好是等会,再尝试发送剩下的字节。
w_wsh76 2009-05-24
  • 打赏
  • 举报
回复
没有错,如果接收端是比较正常的话,建议一次发送8000个字节,留点空余可以自己加一些校验.如果接收端不是正常接收,那就是要先判断每次的发送结果再加尝试次数了.
biweilun 2009-05-24
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 phunxm 的回复:]
谢谢各位的回复。
(1)year2002提到了缓冲区的问题。
Socket默认的缓冲区大小是8KB,请问大数据是不是分批传送?比如要传送100KB的数据过去,代码如下:
int len = 100*1024; // 发送100KB
LPBYTE sendBuffer = new BYTE[len];
int sendCount = 0; // 已经发送的字节数
int left_len = len; // 剩余的字节数
do{
sendCount = this->Send(sendBuffer + len-left_len, left_len, 0);// CAsyncSocket::Send()
le…
[/Quote]
http://news.jobg.cn/articles/20060909/4887.html
hsuhuasu 2009-05-23
  • 打赏
  • 举报
回复
要考虑返回错误码的情况
blackcat242 2009-05-23
  • 打赏
  • 举报
回复
要考虑返回错误码的情况
jilianfeng 2009-05-23
  • 打赏
  • 举报
回复
帮你顶下!~~
  • 打赏
  • 举报
回复
在本地缓冲区满了以后,如果对方没有接收,你的Send始终返回0或者-1(出错),也就是在对方接收完你的数据包之前,你的CPU几乎全耗在这个循环里了,
对方可以慢慢收,但是你没有慢慢发

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧