socket接收数据掉包问题,请教高手?

xiaopan 2012-04-16 11:16:49
我做的是socket client端,而服务端采用的是push的方式,数据通信定义如下:
包长度(4字节),包。先接收包长度4个字节,然后根据这个长度再接收包数据。
我采用的是recv线程,但是有时候得到的长度是无限长和无穷小的负数,郁闷。
但是人家采用的是c#,java写的客户端去接收数据的话,就没有问题,我估计是c#和java已经封装好了。
我该怎么办才好呢?
...全文
520 33 打赏 收藏 转发到动态 举报
写回复
用AI写文章
33 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaopan 2012-04-18
  • 打赏
  • 举报
回复
[Quote=引用 32 楼 的回复:]
引用 31 楼 的回复:
最终确定,是解压函数的问题。
char **UnzipBuffer;
UnzipBuffer = (char **)calloc(5, sizeof(char));
memset(UnzipBuffer, 0, sizeof(UnzipBuffer));

int n = inflate_read(buffer, nRecvLenCount, UnzipBuf……
[/Quote]
谢谢。
昨夜无风 2012-04-18
  • 打赏
  • 举报
回复
[Quote=引用 31 楼 的回复:]
最终确定,是解压函数的问题。
char **UnzipBuffer;
UnzipBuffer = (char **)calloc(5, sizeof(char));
memset(UnzipBuffer, 0, sizeof(UnzipBuffer));

int n = inflate_read(buffer, nRecvLenCount, UnzipBuffer, 1);//解压……
[/Quote]

从上面看,你只分配了一级内存啊,就是UnzipBuffer,并没有分配*UnzipBuffer的内存;你第2维的长度是多少?假如是nLen;改成下面的分配方式:

UnzipBuffer = (char **)calloc(5, sizeof(char*));
memset(UnzipBuffer, 0, 5*sizeof(char*));
for(int i=0;i<5;i++)
UnzipBuffer[i]=malloc(nLen,sizeof(char));


释放的时候也要先释放里面的:
for(int i=0;i<5;i++)
free(UnzipBuffer[i]);
free(UnzipBuffer);
xiaopan 2012-04-18
  • 打赏
  • 举报
回复
最终确定,是解压函数的问题。
char **UnzipBuffer;
UnzipBuffer = (char **)calloc(5, sizeof(char));
memset(UnzipBuffer, 0, sizeof(UnzipBuffer));

int n = inflate_read(buffer, nRecvLenCount, UnzipBuffer, 1);//解压函数/**/

free(*UnzipBuffer);
free(UnzipBuffer);
*UnzipBuffer = NULL;
UnzipBuffer = NULL;

我不知道,这样清除2维指针是否有问题,各位继续帮忙看看。
lazy_2010 2012-04-17
  • 打赏
  • 举报
回复
已经给你思路了啊

需要使用一个缓冲区,保存没有收完整的数据,只有在收到完整的数据之后,才能进行协议分析
tubo_true 2012-04-17
  • 打赏
  • 举报
回复
udp 接收 最好小于 1024 byte , 越小越好

tcp 接收大的数据

xiaopan 2012-04-17
  • 打赏
  • 举报
回复
[Quote=引用 28 楼 的回复:]
逻辑上应该是如下代码,给你参考,这里假定协议数据,不会超过 64K 字节

C/C++ code


BYTE *pbBuf = new BYTE[64 * KBYTES];
UINT uSize = 0;
int nReceived = 0;
while(!bStopClient)
{
// 如果不可以读取,continue;
...
int n ……
[/Quote]
我的这个,有可能大于64K。按照你的做法,是否阻塞在那里,直到读取了4个byte才返回?
lazy_2010 2012-04-17
  • 打赏
  • 举报
回复
逻辑上应该是如下代码,给你参考,这里假定协议数据,不会超过 64K 字节

BYTE *pbBuf = new BYTE[64 * KBYTES];
UINT uSize = 0;
int nReceived = 0;
while(!bStopClient)
{
// 如果不可以读取,continue;
...
int n = recv(clientSocket, pbBuf+nReceived, 64 * KBYTES - nReceived);
if (n < 0)
...;// 错误处理
nReceived += n;
if (nReceived >= 4)
{
uSize = *(UINT *)pbBuf;
if (nReceived >= uSize)
...// 数据接收完整,进行下一步的解析
}
}
xiaopan 2012-04-17
  • 打赏
  • 举报
回复
改成单个接收,也是有问题
if(nRead1 == 0)
{
nRet = recv(m_s, (char *)pDataFirst1, 1, NULL);
nRead1 = 1;
continue;
}
if(nRead2 == 0)
{
nRet = recv(m_s, (char *)pDataFirst2, 1, NULL);
nRead2 = 1;
continue;
}
if(nRead3 == 0)
{
nRet = recv(m_s, (char *)pDataFirst3, 1, NULL);
nRead3 = 1;
continue;
}
if(nRead4 == 0)
{
nRet = recv(m_s, (char *)pDataFirst4, 1, NULL);
nRead4 = 1;
//continue;
}
xiaopan 2012-04-17
  • 打赏
  • 举报
回复

int CHttpSocket::WsaRecFun(char **UnzipBuffer)
{
DWORD dwRecvBytes = 0;
DWORD dwFlags = 0;
DWORD dwIndex = 0;
DWORD dwBufferCount = 1;
//char buffer[BUF_SIZE * 5]={0};
char *buffer;
// memset(buffer, 0, sizeof(buffer));

WSANETWORKEVENTS NetworkEvents;

int nRet = 0;
int nTotal = 0;
int nRecvLen = 0;
int nRecvLenCount = 0;

int nRead1 = 0;
int nRead2 = 0;
int nRead3 = 0;
int nRead4 = 0;

BYTE pDataFirst1[5] = {0};
BYTE pDataFirst2[5] = {0};
BYTE pDataFirst3[5] = {0};
BYTE pDataFirst4[5] = {0};

// while (WaitForSingleObject(hEvent, 0) == WSA_WAIT_TIMEOUT)
while(true)
{
// WSAResetEvent(ClientEventRev);//重置事件

dwIndex = ::WSAWaitForMultipleEvents(1, &ClientEventRev, FALSE, 1000, FALSE);

if(dwIndex == WSA_WAIT_TIMEOUT)// || dwIndex == WSA_WAIT_FAILED
{
// AfxMessageBox("接收超时!");
// return -1;
continue;
}

if(dwIndex == WSA_WAIT_FAILED) // 出现监听错误
{
int nErrorCode = WSAGetLastError();

if(nErrorCode == WSA_INVALID_HANDLE)
{
//AfxMessageBox("监听出现错误:无效的 lphEvents 参数!"); // 代码经常会出现这种错误
return -1;
}
else if(nErrorCode == WSA_INVALID_PARAMETER)
{
//AfxMessageBox("监听出现错误:无效的 CEvents 参数!");
return -1;
}

}

WSAEnumNetworkEvents(m_s, ClientEventRev, &NetworkEvents);//枚举事件

if(NetworkEvents.lNetworkEvents & FD_READ)
// && NetworkEvents.iErrorCode[FD_READ_BIT] == 0)//有可读数据
{
WSAResetEvent(ClientEventRev);//重置事件
// BYTE pDataFirst4[5] = {0};

char pTemp[2] = {0};

if(nTotal == 0)
{
if(nRead1 == 0)
{
nRet = recv(m_s, (char *)pDataFirst1, 1, NULL);
nRead1 = 1;
continue;
}
if(nRead2 == 0)
{
nRet = recv(m_s, (char *)pDataFirst2, 1, NULL);
nRead2 = 1;
continue;
}
if(nRead3 == 0)
{
nRet = recv(m_s, (char *)pDataFirst3, 1, NULL);
nRead3 = 1;
continue;
}
if(nRead4 == 0)
{
nRet = recv(m_s, (char *)pDataFirst4, 1, NULL);
nRead4 = 1;
//continue;
}
nTotal = pDataFirst1[0] + (pDataFirst2[0] << 8) + (pDataFirst3[0] << 16) + (pDataFirst4[0] << 24);;

memset(pDataFirst1, 0, sizeof(pDataFirst1));
memset(pDataFirst2, 0, sizeof(pDataFirst2));
memset(pDataFirst3, 0, sizeof(pDataFirst3));
memset(pDataFirst4, 0, sizeof(pDataFirst4));

buffer = new char[nTotal + 1];

memset(buffer, 0, (nTotal+1) * sizeof(char));

continue;
}

if(nTotal <= 0)
return -1;


nRecvLen = recv(m_s, buffer + nRecvLenCount, nTotal - nRecvLenCount, NULL);

nRecvLenCount = nRecvLenCount + nRecvLen;
if(nRecvLenCount < nTotal)
continue;
else
break;


}


}
int n = inflate_read(buffer, nRecvLenCount, UnzipBuffer, 1);//解压函数

delete []buffer;

if(n < 0)
return -1;

return n;

}
xiaopan 2012-04-17
  • 打赏
  • 举报
回复
还有没有人给点建议啊
csl312211865 2012-04-16
  • 打赏
  • 举报
回复
贴封包和解包代码吧
Eleven 2012-04-16
  • 打赏
  • 举报
回复
是不是你接收端接收数据然后解析写的有问题?
xiaopan 2012-04-16
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 的回复:]
没细看你的代码,不过,从我的分析来看

假如第一次 socket 收到 2 个字节;
然后再收到 2 个字节,
然后再收到后面的有效数据,

似乎这个代码就不能正常处理了
[/Quote]
能否有点思路给我啊,兄弟
lazy_2010 2012-04-16
  • 打赏
  • 举报
回复
没细看你的代码,不过,从我的分析来看

假如第一次 socket 收到 2 个字节;
然后再收到 2 个字节,
然后再收到后面的有效数据,

似乎这个代码就不能正常处理了
xiaopan 2012-04-16
  • 打赏
  • 举报
回复
如果是大小端问题,那就应该收到的数据完全不对,现在是中间丢了
xiaopan 2012-04-16
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 的回复:]
引用 17 楼 的回复:

目前的问题在于,因为接收的是同步数据,同步数据的序列号是递增的,我在接收之后进行解压,发现中间有些序列号是不递增的,比如,序列号末尾都是从0,1,2,。。。。9这几个数字,但是中间可能某个数据丢了,缺了3,等等其他结尾的数据。楼上兄弟说的方法,应该没有用处。因为长度的计算方法,就是我写出来的那个方法:
nTotal = pDataFirst4[0] + (pDat……
[/Quote]
确定,因为我同事用java写的,没有这些问题。他是这样弄的:
len =dis.read() | dis.read()<<8 |dis.read()<<16 |dis.read()<<24;(JAVA)
不知道有什么区别
csl312211865 2012-04-16
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 的回复:]

目前的问题在于,因为接收的是同步数据,同步数据的序列号是递增的,我在接收之后进行解压,发现中间有些序列号是不递增的,比如,序列号末尾都是从0,1,2,。。。。9这几个数字,但是中间可能某个数据丢了,缺了3,等等其他结尾的数据。楼上兄弟说的方法,应该没有用处。因为长度的计算方法,就是我写出来的那个方法:
nTotal = pDataFirst4[0] + (pDataFirst4[1] << 8……
[/Quote]你确定长度的计算方法是对的吗?没有大小端问题?
xiaopan 2012-04-16
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 的回复:]
C/C++ code

nTotal = pDataFirst4[0] + (pDataFirst4[1] << 8) + (pDataFirst4[2] << 16) + (pDataFirst4[3] << 24);

把上面这句,改成

C/C++ code

nTotal = *((int*)pDataFirst4);

试试
[/Quote]
我就不知道我的事件驱动方式有没有问他,调用方式是否存在漏洞
xiaopan 2012-04-16
  • 打赏
  • 举报
回复
目前的问题在于,因为接收的是同步数据,同步数据的序列号是递增的,我在接收之后进行解压,发现中间有些序列号是不递增的,比如,序列号末尾都是从0,1,2,。。。。9这几个数字,但是中间可能某个数据丢了,缺了3,等等其他结尾的数据。楼上兄弟说的方法,应该没有用处。因为长度的计算方法,就是我写出来的那个方法:
nTotal = pDataFirst4[0] + (pDataFirst4[1] << 8) + (pDataFirst4[2] << 16) + (pDataFirst4[3] << 24);

csl312211865 2012-04-16
  • 打赏
  • 举报
回复
nTotal = pDataFirst4[0] + (pDataFirst4[1] << 8) + (pDataFirst4[2] << 16) + (pDataFirst4[3] << 24);

把上面这句,改成
nTotal = *((int*)pDataFirst4);

试试
加载更多回复(13)

18,355

社区成员

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

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