SOCKET中RECV第二次不能阻塞 请高手指教 只顶不给分

Jeff20040819 2009-02-16 09:21:21
服务器客户端建立链接成功,客户端send数据服务器能接受处理,然后服务器tcpServer->Send调用CTcpServer::Send向客户端发送数据,客服端第一次用recv可以阻塞接受数据,但客服端第二次就不能阻塞接受数据了 请问是什么原因?

客户端:
iSend = send(client, (char *)reqPackData, iLen, 0); 第一步:这里先给服务器发送数据

iRecv = recv(client, buff, 1024, 0); 第三步:客户端接受到结构数据处理,这里可以阻塞接受
if (reqPackData->ReqNo == ((ReqPack *)buff)->ReqNo)
{
iRecv = recv(client, buff, 1024, 0); 第五步:应该是接受服务器发送的偏移地址数据,但这步没有阻塞没有接受
}

服务器端:
tcpServer->Send(s, (char *)reqPack, sizeof(ReqPack)); 第二步:服务器处理数据后调用CTcpServer::Send发送结构数据给客服端
tcpServer->Send(s, pCom+reqPack->dwoffset, reqPack->dwSize); 第四步:服务器发送偏移地址数据给客服端
、、、、、、、、、、、、、、、、、、、、、、、、、、、
int CTcpServer::Send(SOCKET s, char *buf, DWORD size)
{
、、、、、、、、、、、、、、、、、、、、、、、、、、、
iSend = WSASend(s, &(PerIoData->DataBuf), 1, &SendBytes, Flags, &(PerIoData->Overlapped), NULL);
、、、、、、、、、、、、、、、、、、、、、、、、、、、
}



开发环境VC.NET2005 那里人气太差了 借本版宝地 请高手指点
...全文
437 30 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
bunnydu 2011-01-28
  • 打赏
  • 举报
回复
能不能更详细的解释一下?
Jeff20040819 2009-02-26
  • 打赏
  • 举报
回复
问题解决了:

iRecv = recv(client, buff, sizeof(ReqPack), 0);

if (reqPackData->ReqNo == ((ReqPack *)buff)->ReqNo++)
iRecv = recv(client, buff, ((ReqPack *)buff)->dwSize, 0);

这样就可以了 感谢大家
joker_yao 2009-02-25
  • 打赏
  • 举报
回复
int check=buff.length;
while (true){
check -= iRecv;
if(check==0){
// 数据已经全部接收
break;
}else{
// 数据已经部分接收
continue;
}

}
// 这是c#的代码
hopewoo 2009-02-21
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 Jeff20040819 的回复:]
我的数据量不大 应该不会出现粘包的现象的
[/Quote]
这个不是数据量大不大的问题,呵呵.
粘包并不是和数据量有关的.


SOCKET client;这个不算流对象,用SYSTEM.IO空间下面的对象.
jedliu 2009-02-21
  • 打赏
  • 举报
回复
很有意思,不但因为是C++,这种情况也值得研究下!
stonehy520 2009-02-21
  • 打赏
  • 举报
回复
不会啊,帮顶
Jeff20040819 2009-02-21
  • 打赏
  • 举报
回复
我的数据量不大 应该不会出现粘包的现象的
yanlongwuhui 2009-02-21
  • 打赏
  • 举报
回复
mark
Jeff20040819 2009-02-21
  • 打赏
  • 举报
回复
第一次服务器向客服端发送结构数据(第二步),这个结构数据非常小,客服端第一次接收(第三步)应该是全部接收了。

我对粘包还不太理解 马上学习下 呵呵 感谢大家的解释 继续向大家学习
Jeff20040819 2009-02-21
  • 打赏
  • 举报
回复
tcp粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。

  出现粘包现象的原因是多方面的,它既可能由发送方造成,也可能由接收方造成。发送方引起的粘包是由tcp协议本身造成的,tcp为提高传输效率,发送方往往要收集到足够多的数据后才发送一包数据。若连续几次发送的数据都很少,通常tcp会根据优化算法把这些数据合成一包后一次发送出去,这样接收方就收到了粘包数据。接收方引起的粘包是由于接收方用户进程不及时接收数据,从而导致粘包现象。这是因为接收方先把收到的数据放在系统接收缓冲区,用户进程从该缓冲区取数据,若下一包数据到达时前一包数据尚未被用户进程取走,则下一包数据放到系统接收缓冲区时就接到前一包数据之后,而用户进程根据预先设定的缓冲区大小从系统接收缓冲区取数据,这样就一次取到了多包数据

选至这里:http://media.ccidnet.com/media/swm/153/06001.htm


我这里应该不是粘包的问题,因为我是单步执行都不可以的;我单步执行到客服端第二次recv(第五步)不阻塞,然后再执行服务器第二次发送数据(第四步)的。

看来我是不是需要直接就这样处理了:服务器端只tcpServer->Send一次,这个数据包包括: (char *)reqPack + pCom+reqPack->dwoffset(也就是把结构体数据与偏移地址数据一起发送),客服端也只接收一次:iRecv = recv(client, buff, 1024, 0);
应该这样要好些吧 请大家指点下,服务器端程序是别人做好了的 这样我就要改他的程序了
Jeff20040819 2009-02-21
  • 打赏
  • 举报
回复
TO:

SOCKET client;这个不算流对象,用SYSTEM.IO空间下面的对象.

具体是用SYSTEM.IO下面的哪个类哦???能说具体些吗? 谢谢
homejiji 2009-02-20
  • 打赏
  • 举报
回复
另外你说的阻塞是客户端阻塞,服务器可不管你,服务器第一次和第2次发送不会管你客户端是不是阻塞的,而是连续发送了,发送的数据首先保存在客户端的socek缓存里面,用recv实际是从socek缓存中将数据取出
homejiji 2009-02-20
  • 打赏
  • 举报
回复
服务器在发送的时候是连续发送的。。。正像hopewoo 说的应该是发生粘包了
而客户端在接收的时候没有对粘包的情况做处理,很有可能第一次接收的时候就把数据都接收完了
Jeff20040819 2009-02-20
  • 打赏
  • 举报
回复
SOCKET client;
Jeff20040819 2009-02-19
  • 打赏
  • 举报
回复
TO:hopewoo

client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

iRecv = recv(client, buff, 1024, 0); 中的client就是个流对象

hopewoo 2009-02-19
  • 打赏
  • 举报
回复
client 是什么类型,发我看看
sxmonsy 2009-02-18
  • 打赏
  • 举报
回复
帮顶
hopewoo 2009-02-18
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 cg2003 的回复:]
TO:hopewoo

我看了下,估计是粘包了。
iRecv = recv(client, buff, 1024, 0); 第三步:客户端接受到结构数据处理,这里可以阻塞接受
已经把所有数据发送过来了。


这里的确阻塞接受了服务器第一次发送的全部数据;我的目的是:服务器第一次(第二步)发送结构数据,客户端第一次用recv(第三步)接受处理,如果这个结构数据正确,客服端第二次用recv(第五步)接受服务器第二次(第四步)发送的偏移地址中的数据,…
[/Quote]

这个我推荐你用流对象来接受,你那个我现在可以肯定是粘包了,没有按照你的想法来发送.
要解决这个东西,一般推荐用异步的接受,或者用类似BinaryReader 的对象来读取.
che2piaopiao 2009-02-18
  • 打赏
  • 举报
回复
我也要学Socket!
大神来了丶 2009-02-17
  • 打赏
  • 举报
回复
不懂 学习 帮顶
加载更多回复(10)

111,097

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

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