|

楼主 |
发表于 2007-10-30 23:25:00
|
显示全部楼层
Re:tcp中拼包,拆包,粘包,这些问题怎么处理??
终于搞定了,服务器和客户端都是异步传输,而且都是完成端口,算是领悟了完成端口的本质,就是一个很优良的IO模型而已,我的错误在于不断的发出数据接受的请求,前一次发送没有完成是不能发接受请求的
virtual void OnWrite(const DWORD dwByteCount, Session* lpSession, LPPER_IO_DATA PerIoData)
{
lpSession->lpBufEnd += dwByteCount; //更新已经发完的部分
int sended = lpSession->lpBufEnd - lpSession->arrayDataBuf; //已发的长度
short int paclen = *(short int*) ( lpSession->arrayDataBuf + 3); //后面两位表示数据包的长度
if(sended < paclen) //还没发完
{
//还没发完继续发...
PerIoData->wDataBuf.buf = (char *)lpSession->lpBufEnd; //发剩下部分
PerIoData->wDataBuf.len = paclen - sended;
PerIoData->dwFlags = 0;
PerIoData->dwOpCode = OP_WRITE;
if(WSASend(PerIoData->socket, & erIoData->wDataBuf, 1, &PerIoData->dwBytes,
MSG_PARTIAL, &PerIoData->Overlapped, NULL) == SOCKET_ERROR)
{
if(WSAGetLastError() != ERROR_IO_PENDING)
{
g_Log.Log(DEBUG_LV, "WSASend() failed with error- %d\n", WSAGetLastError());
return ;
}
}
}
else
{
lpSession->lpBufEnd = lpSession->arrayDataBuf;
ZeroMemory(lpSession->arrayDataBuf,sizeof(lpSession->arrayDataBuf));
SendRev(PerIoData, IO_BUFFER_LONGTH); //表明数据发送完成了,这个时候投递请求好了
}
这才是本质,现在的问题都解决了,我采用了不定长的发送方式,还是12楼的做法
领会了:
=============================================================================
只不过在客户端的工作线程中,得到的完成通知的已发送字节数不一定是所有的,这里就需要再次提交WSASend剩下的字节数(一定是剩下的所有字节数)。
===========================
以及:
=====================================
一次投递所有字节,会保证字节的相对顺序,而且IOCP内部的调度比起你自己分包WSASend要高效和具有伸缩性。
============================================================================
这两句话的含义,按照这样的方法发送数据,性能才是优良的。 |
|