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++;

}
...全文
9528 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是在接收端出现的。
看不见的裂痕 2012-10-15
  • 打赏
  • 举报
回复
VS菜单中的Tools下面有个Error Lookup里面可以直接根据错误码查询的。
Mark下,漫漫看
sumos 2012-10-15
  • 打赏
  • 举报
回复
这是MS的解释。
【无法立即完成一个非阻止性套接字操作。】
内容概要:本文围绕双机并联虚拟同步发电机(VSG)在微电网中的功率分配、黑启动及预同步控制展开深入研究,重点提出了一种结合惯量与阻尼协同自适应控制的策略,以提升微电网在孤岛与并网模式下的频率稳定性及动态响应性能。通过Simulink搭建双VSG并联系统仿真模型,系统实现了有功/无功功率均分、微电网黑启动过程模拟、并网前的预同步控制,并引入虚拟阻抗技术以优化环流抑制。研究涵盖控制策略设计、系统建模、参数整定与仿真验证全过程,旨在增强微电网运行的可靠性、稳定性和自主恢复能力。; 适合人群:具备电力系统、微电网、电力电子及自动控制等相关专业知识,从事新能源发电、分布式能源系统、VSG控制技术等领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①掌握双机VSG并联系统的建模与仿真方法;②深入理解微电网黑启动机制与预同步控制的实现流程;③研究VSG惯量-阻尼自适应调控对系统频率稳定性和动态性能的影响;④为构网型储能、微电网能量管理系统及VSG控制器的设计与优化提供可靠的仿真验证平台。; 阅读建议:建议结合Simulink仿真模型同步学习,重点关注VSG控制环路、虚拟阻抗设计及预同步逻辑的实现细节;在复现过程中应逐步调试各功能模块,理解黑启动与预同步的时序逻辑,并通过改变负载、线路参数或初始频率偏差等方式验证系统的鲁棒性与适应性。
内容概要:本文详细介绍了一种基于Simulink仿真实现的直流电机转速电流双闭环调速控制系统模型,系统通过构建电流环与转速环两个闭环控制回路,结合PID控制器实现对直流电机转速和电枢电流的精确调节,有效提升了系统的动态响应速度、稳态精度及抗负载扰动能力。文中阐述了系统建模的关键环节,包括电机数学模型建立、PI控制器参数整定、电流检测与反馈、速度反馈处理以及PWM驱动模块设计,并通过仿真实验验证了双闭环结构相较于单闭环在控制性能上的显著优势,适用于深入理解现代电机控制策略的核心原理与工程实现方法; 适合人群:自动化、电气工程、机电一体化等相关专业的本科生、研究生,以及从事电机驱动系统开发、电力电子与运动控制领域的科研人员和工程技术人员; 使用场景及目标:①用于高校课程教学与实验,帮助学生掌握双闭环控制的基本原理与仿真技能;②作为科研项目中电机控制算法的验证平台,支持先进控制策略(如模糊控制、自适应控制)的开发与测试;③为工业现场高性能直流调速系统的设计与优化提供理论依据和技术参考; 阅读建议:建议读者结合自动控制理论与电机拖动基础知识进行学习,重点关注PID参数的整定过程与系统阶跃响应特性分析,可通过调整负载转矩、给定转速等条件,观察系统鲁棒性与动态性能变化,进一步深化对闭环控制机制的理解。

18,356

社区成员

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

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