狂晕,recv()出现奇怪错误!高手请出招

Semigod 2003-11-13 06:02:12
我使用blocking mode的socket,在接收数据时,第一次调用recv会成功,但
只能收到一部分数据,再次调用recv()接收剩余数据时,出错,返回错误是10038
也就是无效socket,但我保证socket没有错。

我甚至尝试按异步socket处理,在接收前加上下面这样一段代码来确保有数据可接收都没用!
这是为什么??????????????????
...全文
240 33 打赏 收藏 转发到动态 举报
写回复
用AI写文章
33 条回复
切换为时间正序
请发表友善的回复…
发表回复
Semigod 2003-11-20
  • 打赏
  • 举报
回复

在BinaryTreeEx的帮助下搞定了,谢谢大家,另开贴给分!

原因出在ParseResponseHeader()一句上,我的代码在检测服务器返回的HTTP头部内容时,
发现服务器返回了 Connection: close 一句便立即断开了连接,所以后面的数据没法再接收了。

这100分给这里出现了的人

另请fbmsf(FBM) BinaryTreeEx
到http://expert.csdn.net/Expert/topic/2475/2475669.xml?temp=.499859领分
fbmsf 2003-11-19
  • 打赏
  • 举报
回复
哈哈,很快就成功了,那时你对winsock 的理解又更加深刻了
Semigod 2003-11-18
  • 打赏
  • 举报
回复
试了,结果还是收不完整,不管第一次接收时buffer是否被填满了

Semigod 2003-11-18
  • 打赏
  • 举报
回复
好,试一下
fbmsf 2003-11-18
  • 打赏
  • 举报
回复
这样,你先做一个实验,不用http,收网页的数据,
而是你另外做一个服务程序,用来发送17k的数据,看用你的代码(recv)可以全部收到不?

我想知道到底是因为收的网页的问题还是你的代码的问题?
Semigod 2003-11-18
  • 打赏
  • 举报
回复
不行,结果一个样

惨啊,几天了都没搞定这个问题
Semigod 2003-11-18
  • 打赏
  • 举报
回复
fbmsf(FBM) 谢谢你了,搞定了请你吃分数套餐 :)

我试下先
Semigod 2003-11-18
  • 打赏
  • 举报
回复
感谢大家!我是现实派的 :)

正在狂调试.......................
fbmsf 2003-11-18
  • 打赏
  • 举报
回复
我估计也许是的你接收缓冲区有问题,


我写的每次收1k 的,即便是几GB的数据(收发文件夹)也没有过问题。

帮你想.........
Semigod 2003-11-18
  • 打赏
  • 举报
回复
真是怪,我上面给出的代码基本上算是与收发相关的全部代码了,而我这里是局域网通过ADSL上网。
大家多帮帮忙啊。
catyou 2003-11-18
  • 打赏
  • 举报
回复
应该是你的接收有问题,我们在广域网通过拨vpn测试,发送36K的数据也没有问题,每个包只传输1k的数据。在局域网一次发送36k,接收也没问题。
Semigod 2003-11-17
  • 打赏
  • 举报
回复
我又晕!~~~~~~~~~~~~~~~

刚试把把接收部分改为 异步接收 ,结果一样,我操!

下面是我改为异步接收后的代码片断:
====================================================================
HANDLE hEvent = WSACreateEvent();
if (hEvent != WSA_INVALID_EVENT)
{
if (WSAEventSelect(sckHTTPSocket, hEvent, FD_READ) == 0 &&
WSAWaitForMultipleEvents(1, &hEvent, FALSE, m_nRecvTimeout, FALSE) != WAIT_OBJECT_0)
{
free(pBuffer);
return NULL;
}
CloseHandle(hEvent);
}

WSABUF buf;
buf.buf = pBuffer+iRecvSize;
buf.len = iBufferSize - iRecvSize;
DWORD curSize;
DWORD flags = 0;
int iErr = WSARecv(sckHTTPSocket, &buf, 1, &curSize, &flags, NULL, NULL);
int i = WSAGetLastError(); // 第二次执行到这里时,iErr = -1 , i = 10038
Semigod 2003-11-17
  • 打赏
  • 举报
回复
我又晕!~~~~~~~~~~~~~~~

刚试把把接收部分改为 异步接收 ,结果一样,我操!

下面是我改为异步接收后的代码片断:
====================================================================
HANDLE hEvent = WSACreateEvent();
if (hEvent != WSA_INVALID_EVENT)
{
if (WSAEventSelect(sckHTTPSocket, hEvent, FD_READ) == 0 &&
WSAWaitForMultipleEvents(1, &hEvent, FALSE, m_nRecvTimeout, FALSE) != WAIT_OBJECT_0)
{
free(pBuffer);
return NULL;
}
CloseHandle(hEvent);
}

WSABUF buf;
buf.buf = pBuffer+iRecvSize;
buf.len = iBufferSize - iRecvSize;
DWORD curSize;
DWORD flags = 0;
int iErr = WSARecv(sckHTTPSocket, &buf, 1, &curSize, &flags, NULL, NULL);
int i = WSAGetLastError(); // 第二次执行到这里时,iErr = -1 , i = 10038
Semigod 2003-11-17
  • 打赏
  • 举报
回复
我没有发送程序,我是连接到一个网站来测试的,那个网站返回的HTML页面数据大于16K,我建立了一个16K的缓冲区,但在接收循环中的第一次时只能收到 8712 Bytes 的数据,第二次循环时就出错了。
很奇怪,这个收到的数据长度总是这个值!

我试着用 telnet www.???.com 80连接进去
然后发送 GET /index.htm HTTP/1.0
Host: www.???.com

过去,telnet得到的数据就是全部index.htm页面,而我的程序就不行 :(


我要给这个另外加分了,看来100分不够,再加100分,另开贴给分。
farfh 2003-11-17
  • 打赏
  • 举报
回复
在我的记忆中10038错误,只有可能是对方或者自己关闭了套节字才会出现。
建议你相信GetLastError()给出的错误代码和msdn的解释
这样的话,如果不是由于你自己关闭了socket,那么就是服务器方已经关闭了。
另外建议客户端使用异步,同时在SOCKET上等待FD_READ和FD_CLOSE消息,这样,应该可以确认是否对方关闭了套节字造成了错误。如果确实等到了FD_READ消息而出现10038错误,那么大概就是在数据传输过程中,对方关闭了套节字。
(小弟菜鸟,胡乱说两句,不对也别见怪哈^_^)
catyou 2003-11-17
  • 打赏
  • 举报
回复
我建议你可以测试只传输1K的字节测试一下,分两次或多次,看看什么时候会出现接收数据错的情况。收取之后,对数据不处理,也就是说不经过延时,重新接收,看看能接收多少次。
Semigod 2003-11-17
  • 打赏
  • 举报
回复
就是没有收够啊, 我给16K的缓冲区,也只能收4K多一些,每次收到的数据好像都一样长,只是不够,这个时候应该可以再次调用recv来接收剩下部分的,可是一调用就出错了!
fbmsf 2003-11-17
  • 打赏
  • 举报
回复
用组塞模式,先不用select了,就是循环调用recv,收一次,累加一次,弹一个MessageBox,

看看到底收了多少,


这个问题不难,我应该可以帮你搞定。
Semigod 2003-11-17
  • 打赏
  • 举报
回复
另外,我原本是使用blocking mode的,因为出了这个问题,所以改为non-blocking mode,为了确保调用recv时有数据可读,我使用了FD_READ并等待事件,结果还是不行。

附:据MSDN说 发生10038(无效socket)错误时,有两种可能:
1. socket句柄确实无效
2. select 参数有错
我估计是问题可能是第二个原因,但为什么第一次时是可以的?

我程序中用到的select代码(注:前面代码中的select不影响)
=======================================================

struct fd_set fdSet;
struct timeval tmvTimeout={0L,0L};

FD_ZERO(&fdSet);
FD_SET(sckHTTPSocket, &fdSet);

if ( select(0,&fdSet,NULL,NULL,&tmvTimeout)==SOCKET_ERROR)
{
。。。。
}

Semigod 2003-11-17
  • 打赏
  • 举报
回复
没有,第一次没有收到全部数据,只收了 8712个字节,全部数据长度大于16K,
我判断收到数据的长度不是用strcpy之类来判断的,而是依据 recv()的返回值来判断的。
加载更多回复(13)

18,356

社区成员

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

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