socket 客户端接收数据不全!~

jilianfeng 2009-11-28 10:38:45
如题:
我是使用异步事件 进行接收数据的!请哪位老大指点下,如何才能接受全部的数据!接受步骤如下!

void CMYDlg::wss()//给服务端发送数据
{
tjz();
char sendText[100];
int numsnt,status;

sprintf(sendText,"WSS:%s$%s$%s",uname,city,Sb);

//MessageBox(sendText);
numsnt=send(ClientSock2, sendText, strlen(sendText) + 1, NO_FLAGS_SET);

if (numsnt!= (int)strlen(sendText)+1)
{
// MessageBox("ERROR: Connection terminated!","aasasa",MB_OK);
//status=closesocket( ClientSock2);
if (status == SOCKET_ERROR)
// MessageBox("ERROR: closesocket unsuccessful!","aa",MB_OK);
//status=WSACleanup();
closesocket( ClientSock2);
// if (status == SOCKET_ERROR)
// MessageBox("ERROR: WSACleanup unsuccessful!","aa",MB_OK);
return ;
}
//MessageBox(sendText);
else
{
if(WSAAsyncSelect(ClientSock2, m_hWnd, NETWORK_EVENT, FD_CLOSE | FD_READ ) == SOCKET_ERROR)
{
// MessageBox("注册网络异步事件失败!");
WSACleanup();

}
}
//MessageBox("异步成功");
}
void CMYDlg::OnNetEvent(WPARAM wParam, LPARAM lParam)
{
int iEvent1 = WSAGETSELECTEVENT(lParam);
//调用Winsock API函数,得到发生此事件的客户端套接字
SOCKET CurSock= (SOCKET)wParam;
switch(iEvent1)
{

case FD_READ: //网络数据包到达事件
OnReceive( CurSock);
break;


case FD_CLOSE: //客户端断开事件
OnClose( CurSock);
break;
default: break;
}
}

void CZKDlg::OnReceive(SOCKET CurSock)
{
try
{
char recvText[40480];
int numrcv;
Sleep(500);
numrcv=recv(ClientSock2, recvText, 40480,0);
if ((numrcv == 0) || (numrcv == SOCKET_ERROR))
{
//MessageBox("ERROR: Connection terminated!","aa",MB_OK);
status=closesocket(ClientSock2);
if (status == SOCKET_ERROR)
//MessageBox("ERROR: closesocket unsuccessful!","aa",MB_OK);
status=WSACleanup();
//if (status == SOCKET_ERROR)
// MessageBox("ERROR: WSACleanup unsuccessful!","aa",MB_OK);

}
recvText[numrcv]='\0';//这里接收到得 数据 有的时候不全,请问哪位老大能告诉如何修改接收的代码能使数据完全接收!

//MessageBox(recvText);
}
...全文
1114 30 打赏 收藏 转发到动态 举报
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
IO2 2009-12-02
  • 打赏
  • 举报
回复
搞不懂,接分~
ydyn1988 2009-12-01
  • 打赏
  • 举报
回复
需要循环判断套接字是否可读
ydyn1988 2009-12-01
  • 打赏
  • 举报
回复
int startTime = ::GetTickCount();
do{
if((GetTickCount() - startTime) > TIMEOUT){
// out of time
// do by youself
}
///////////////////////////////////////////
timeval timeout;
fd_set fs;
FD_ZERO(&fs);
FD_SET(m_pServerSocket->m_hSocket, &fs);
int status = ::select(0, &fs, NULL, NULL, &timeout);

// judge if the socket readale

if(status == SOCKET_ERROR){
return 0;
}
else if(!status){
::Sleep(688);
continue;
}
///////////////////////////////////////
::Sleep(288);
ret=recv(Your_socket, buffer,nLen, 0);
if(ret == SOCKET_ERROR){
return FALSE;
}
else{
// save buffer
}
startTime = GetTickCount();
}while(1);

Pro_X 2009-12-01
  • 打赏
  • 举报
回复
正解!结贴给分啊。
jenf 2009-12-01
  • 打赏
  • 举报
回复
char recvText[40480];
int numrcv;
Sleep(500);
numrcv=recv(ClientSock2, recvText, 40480,0);
if ((numrcv == 0) || (numrcv == SOCKET_ERROR))
{
//MessageBox("ERROR: Connection terminated!","aa",MB_OK);
status=closesocket(ClientSock2);
if (status == SOCKET_ERROR)
//MessageBox("ERROR: closesocket unsuccessful!","aa",MB_OK);
status=WSACleanup();
//if (status == SOCKET_ERROR)
// MessageBox("ERROR: WSACleanup unsuccessful!","aa",MB_OK);

}
else
{
memcpy(m_szrcvBuf+m_nrcvBufLen, recvText, numrcv); // 将每次接收的数据缓存
m_nrcvBufLen += numrcv; // 修改缓存的位置,以便下次继续缓存
if (m_nrcvBufLen == 你确定正确的数据长度) // 这里不一定是这么处理,你还可以给你的包加上结束符根据结束符判断
{
... // 处理m_szrcvBuf中的数据
m_nrcvBufLen = 0; // 表示缓存已空
}
//////////////////////////////////////////////////////////////////////////
// m_szrcvBuf应该是一个足够大的char数组,m_nrcvBufLen是一个int或long int,需要初始化为0
}
jilianfeng 2009-12-01
  • 打赏
  • 举报
回复
谁来帮我看看 啊!~
jilianfeng 2009-11-30
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 gordenyue 的回复:]
数据比较多的时候,new一个空间用于接收数据,不要申请临时的。
[/Quote]
[Quote=引用 23 楼 wnx_u 的回复:]
建个议吧,你发的时候别一起就发了,比如最多发1000个字节,而且自定义一个协议这样发就好多了
一般只有UDP协议才用事件IO模型,但是我看你的API函数好像是TCP协议的,不解你的意思
还有,你就按你这样,用setsockopt把缓冲区设大些看看,如果还是一样的结果,就不是缓区的问题了
[/Quote]
不是缓冲区的问题!就是接收的时候 没接收全 就继续往下运行了!
jilianfeng 2009-11-30
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 xuxingok 的回复:]
5楼、6楼说了

只不过不止recv要有while循环接数据,send也要有while循环发数据
[/Quote]
但是不清楚 该如何去写!能帮个忙 写个例子么?而且 5.6 楼 我测试了下 代码不对@!
xuxingok 2009-11-30
  • 打赏
  • 举报
回复
5楼、6楼说了

只不过不止recv要有while循环接数据,send也要有while循环发数据
jilianfeng 2009-11-30
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 gooer 的回复:]
不是很清楚你用的UDP 还是TCP

UDP: 有可能是你接收到的socket的缓冲区太小,无法接收到整包,FD_READ只触发一次,余下的数据不会再次触发 FD_READ;

TCP:  支持 zhou1zhou8 的看法

使用事件,不可以对一个 FD_READ进行多次 rec(); 需要先关闭事件
[/Quote]
我使用的是 tcp!~
jilianfeng 2009-11-30
  • 打赏
  • 举报
回复
还是没解决啊!~~~
wnx_u 2009-11-30
  • 打赏
  • 举报
回复
建个议吧,你发的时候别一起就发了,比如最多发1000个字节,而且自定义一个协议这样发就好多了
一般只有UDP协议才用事件IO模型,但是我看你的API函数好像是TCP协议的,不解你的意思
还有,你就按你这样,用setsockopt把缓冲区设大些看看,如果还是一样的结果,就不是缓区的问题了
gordenyue 2009-11-30
  • 打赏
  • 举报
回复
数据比较多的时候,new一个空间用于接收数据,不要申请临时的。
jilianfeng 2009-11-30
  • 打赏
  • 举报
回复
来帮帮我啊啊!~
tan625747 2009-11-29
  • 打赏
  • 举报
回复
numrcv=recv(ClientSock2, recvText, 40480,0);
为什么不把4080改成 sizeof(recvText)呢
Pro_X 2009-11-29
  • 打赏
  • 举报
回复
解决了?还是没解决?
Dingnifei123 2009-11-29
  • 打赏
  • 举报
回复
问题该解决了吧,

俺接分了。
icycode 2009-11-29
  • 打赏
  • 举报
回复
是不是recv的缓冲区太小了,应该循环接收直到没有数据为止。
gooer 2009-11-29
  • 打赏
  • 举报
回复
不是很清楚你用的UDP 还是TCP

UDP: 有可能是你接收到的socket的缓冲区太小,无法接收到整包,FD_READ只触发一次,余下的数据不会再次触发 FD_READ;

TCP: 支持 zhou1zhou8 的看法

使用事件,不可以对一个 FD_READ进行多次 rec(); 需要先关闭事件
starwalker 2009-11-28
  • 打赏
  • 举报
回复
楼上的代码有问题,每次循环都会把上次的数据覆盖掉
至少应该这么写:
numrcv = 0;
while(numrcv < 40480) // 40480需要事先知道(先传过来或者与发送端约定好)
{
numrcv += recv(ClientSock2, recvText + numrcv, 40480,0);
}
加载更多回复(10)

18,356

社区成员

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

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