TCP socket读数据的时候经常返回10035的错误。

96掌门师兄 2012-10-15 02:58:02
我使用TCP协议来传送每秒15帧的视频数据(每帧大小约为70KB,每秒大约1MB的数据),接收端使用select IO模型,当有数据可读的时候从套接口读数据。socket的接收缓冲区修改为2Mb

但是读的时候经常返回10035的错误,大家帮忙分析一下,谢谢了!
发送端对TCP的socket进行了select判断,为可读后再发送。
类似这种大数据量的TCP发送数据,大家一般是如何发送和接收的呢?
代码如下,不是很好理解,让你们费心了,再次感谢.
memset(g_pRecvBuf, 0, MAXRECVBUFLEN); //g_pRecvBuf是接收区,大小为1Mb 0x100000
long lMsgSize;
int iLen = recv((*iter)->m_pComm->m_fdSocket, (char *)&lMsgSize, sizeof(long), 0);
if((iLen <= 0)||(lMsgSize < 0))
{
if(lMsgSize < 0)
{
RUNFILELOG(TLogLevel_Debug, "recv msg error: video data size < 0 .");

}
(*iter)->m_pComm->closeSocket();
DELETE_P((*iter)->m_pComm);
TMainCtrl::instance()->getXlwSimEntity()->m_bConnect = false; //断链,需要重连
RUNFILELOG(TLogLevel_Debug, "Socket Error and ReConnect.");
return ;

}
OspPrintf(TRUE, FALSE, "video data size %d \n", lMsgSize);
int bytes_read = 0;
char *recvptr = NULL;
int iCount = 0;
bytes_left = lMsgSize;
recvptr = g_pRecvBuf;
int err = 0;
fd_set scanSet;

//扫描等待时间
struct timeval waitTime;
int begainRecvTime = time(NULL);
int currentRecvTime = begainRecvTime;
while(bytes_left > 0) //这里循环的接收。
{

currentRecvTime = time(NULL);
if(currentRecvTime - begainRecvTime > 1 || (iCount == 1 && bytes_read == 0))
{
RUNFILELOG(TLogLevel_Error, "There is no any receive data (bytes_left:%d total :%d) MaxRecvTimes:%d!", bytes_left, lMsgSize, MaxRecvTimes);
return;
}
int fdSock =(*iter)->m_pComm->m_fdSocket;
bytes_read = recv(fdSock, recvptr, bytes_left, 0);
if(bytes_read < 0)
{
#ifdef _WIN32
err = WSAGetLastError();
if(WSAEWOULDBLOCK == err || WSAEINPROGRESS == err)
#else
if ( (errno == EAGAIN) || ( errno == EINTR))
#endif
{
bytes_read = 0; //是否是错误? 或者因为循环的时候的确没有数据,是正常的情况? RUNFILELOG(TLogLevel_Debug, "recv data err %d.", err);
}
else //if(WSAETIMEDOUT == err || WSAENETDOWN == err)
{
(*iter)->m_pComm->closeSocket();
DELETE_P((*iter)->m_pComm);
TMainCtrl::instance()->getXlwSimEntity()->m_bConnect = false; //断链,需要重连
RUNFILELOG(TLogLevel_Debug, "Socket Error and ReConnect.");
}
}
else if(bytes_read == 0)
{
#ifdef _WIN32
err = WSAGetLastError();
RUNFILELOG(TLogLevel_Error,"read (FD=%d) failed, errno=%d", fdSock, err);
#else
RUNFILELOG(TLogLevel_Error,"read (FD=%d) failed, err=%d", fdSock, errno);
#endif
}
bytes_left -= bytes_read;
recvptr += bytes_read;
iCount++;
}



发送端得代码。
while(bytes_left>0)
{

currentSendTime = time(NULL);
if(currentSendTime - begainSendTime >= MaxSendTimes)
{
LOG_DEBUG(true, "Send Reach the max Time:%", MaxSendTimes);
return FALSE;
}
FD_ZERO(&scanSet);//初始化fd_set
FD_SET(fd_sock, &scanSet);//分配套接字句柄到相应的fd_set
waitTime.tv_sec = 0;
waitTime.tv_usec = 20*1000;

s32 select_ret = 0;

//判断可写(防止缓冲区爆满)
select_ret = select(FD_SETSIZE, (fd_set *)0, &scanSet, (fd_set *)0, &waitTime) ;
written_bytes = send(fd_sock, writePtr, bytes_left, 0);
if(written_bytes<=0) /* 出错了*/
{
#ifdef _WIN32
int err = WSAGetLastError();
#else
int err = errno;
#endif
#ifdef _WIN32
if(err == WSAECONNABORTED || err == WSAEWOULDBLOCK || WSAEINPROGRESS == err)
#else
if(errno == EAGAIN || errno == EINTR) /* 中断错误 我们继续写*/
#endif
{
written_bytes=0;
LOG_DEBUG(true, "send packet error.");
}
else /* 其他错误 没有办法,只好撤退了*/
{

//做一些处理
LOG_DEBUG(true, "socket error and stop send data.");
g_bSendVideo = false;

//return FALSE;
}
}
bytes_left -= written_bytes;
writePtr += written_bytes; /* 从剩下的地方继续写 */
if(iCount > 1)
{
LOG_DEBUG(true, "send a frame more than one time");
}
iCount++;

}
...全文
8430 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
弱水垂钓 2012-10-17
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 的回复:]

引用 7 楼 的回复:
最近刚看了一本网络编程的书,帮你分析一下问题。
1. 第一个recv接收长度lMsgSize,潜在问题是如果到达的数据小于4个字节,是不正确的,最好判断收到4个字节后再往下走。
2. 第二个接收数据的recv,返回10035是正常的,因为对方的数据没有到达,错误码是WSAEWOULDBLOCK。解决方法:
2.1 用setsockopt(SO_RCVTIMEO)……
[/Quote]
楼主判断了吗?select的返回值,只是取了而已
cxs_ch 2012-10-17
  • 打赏
  • 举报
回复
select之后,好像没有对结果进行判断,是有可读或者可写等,而直接调用了send和recv。
ShengFei01 2012-10-17
  • 打赏
  • 举报
回复
不一定是对方没有及时接收,发送返回10035有下面原因:
1. 本机发送的速度大于网络传输的速度;
2. 中间路由器的处理速度小于本机发送的速度;
3. 对方没有及时接收,你所提到的。
解决方法:发送返回10035时,把socket加入写描述符集合,当select返回时如果你的socket在可写集合中再调用send就行了。
bsnry 2012-10-17
  • 打赏
  • 举报
回复
好贴,mark一下, 有空再看
96掌门师兄 2012-10-16
  • 打赏
  • 举报
回复
顶起来啊,
96掌门师兄 2012-10-16
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 的回复:]
最近刚看了一本网络编程的书,帮你分析一下问题。
1. 第一个recv接收长度lMsgSize,潜在问题是如果到达的数据小于4个字节,是不正确的,最好判断收到4个字节后再往下走。
2. 第二个接收数据的recv,返回10035是正常的,因为对方的数据没有到达,错误码是WSAEWOULDBLOCK。解决方法:
2.1 用setsockopt(SO_RCVTIMEO)设置一个接收的超时时间。适……
[/Quote]
多谢了。
我在接收端的上层已经对这个socket进行了select判断,是判断到有数据可读时,才进行收的,在这个 收的过程中,还可以进行select吗? 上层的select为可读不是已经说明有数据来了吗? 只要是有数据来,不管是不是完整数据select都可读吗?
你看的是哪本书啊?求推荐。
96掌门师兄 2012-10-16
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 的回复:]
#8楼:
看的是《WinSock网络编程经络》,写的很不错,之前看论坛上的问题都不懂,现在都可以回答了。你上层判断可读是没问题。但具体有多少数据你是不知道的。而recv每次返回的是协议队列中数据。
如果你第一次recv 4个字节,可能对方只发了这么多,再调用recv就会因为没有数据而返回10035。建议你分配大一点的缓冲区,把第一次接收的前4个字节转换为lMsgSize,后面的做为数据,这样只……
[/Quote]

恩,我的缓冲区设置为2*1024*1024 2M,但是发送端也还是常出现10035,说明接收端没有及时处理数据。。。我的接收端开启的是100个这样的进程,1000M网卡,linux的系统。。
ShengFei01 2012-10-16
  • 打赏
  • 举报
回复
#8楼:
看的是《WinSock网络编程经络》,写的很不错,之前看论坛上的问题都不懂,现在都可以回答了。你上层判断可读是没问题。但具体有多少数据你是不知道的。而recv每次返回的是协议队列中数据。
如果你第一次recv 4个字节,可能对方只发了这么多,再调用recv就会因为没有数据而返回10035。建议你分配大一点的缓冲区,把第一次接收的前4个字节转换为lMsgSize,后面的做为数据,这样只需要调用一次recv就知道接收数据的多少。比如你的缓冲区是2048,而recv返回4个字节,说明现在只有4个字节,不需要再调用recv,等下次再判定可读时再调用就可以了。
ShengFei01 2012-10-15
  • 打赏
  • 举报
回复
最近刚看了一本网络编程的书,帮你分析一下问题。
1. 第一个recv接收长度lMsgSize,潜在问题是如果到达的数据小于4个字节,是不正确的,最好判断收到4个字节后再往下走。
2. 第二个接收数据的recv,返回10035是正常的,因为对方的数据没有到达,错误码是WSAEWOULDBLOCK。解决方法:
2.1 用setsockopt(SO_RCVTIMEO)设置一个接收的超时时间。适用于阻塞socket
2.2 把你的socket放入可读集合,用select确定何时数据到达。适用于非阻塞socket。
这样你的while不用总执行,有数据才调用recv,效率比较高。这是我学习时找到的代码:
http://download.csdn.net/detail/geoff08zhang/4571358
luawkk 2012-10-15
  • 打赏
  • 举报
回复
异步处理的话 这个 10035可以忽略的
wjb_yd 2012-10-15
  • 打赏
  • 举报
回复
你也可以用阻塞的recv和send,就是会卡住所在的线程。
wjb_yd 2012-10-15
  • 打赏
  • 举报
回复
recv的时候返回10035很正常啊,IOCP就是用来解决大并发连接异步IO的问题的。
你投递了WSARECV之后,返回-1,并且WSAGetLastError=10035,说明这个异步IO已经投递到网络层了,只不过当前接收缓冲区内没有数据,需要网络层接收到数据之后,由操作系统通知你异步IO已经完成,即GetQueuedCompletionStatus。
96掌门师兄 2012-10-15
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]
这是MS的解释。
【无法立即完成一个非阻止性套接字操作。】
[/Quote]

返回值的意义我懂。 就是想问一下,是不是远程流式套接字 socket缓冲区满了,发送端就不发或者发送减慢呢? 发送端是怎么知道远程socket满的?(TCP协议自己实现了通知吗?)

这个10035是在接收端出现的。
傻X 2012-10-15
  • 打赏
  • 举报
回复
VS菜单中的Tools下面有个Error Lookup里面可以直接根据错误码查询的。
Mark下,漫漫看
sumos 2012-10-15
  • 打赏
  • 举报
回复
这是MS的解释。
【无法立即完成一个非阻止性套接字操作。】

18,356

社区成员

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

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