请问该如何正确接收大数据量的数据
公司现正做一个项目,做一个服务器该服务器实现同其他公司的通信接口,对其他的公司的通信接口来说
我的服务器是客户端
同时我的服务器还要管理自己写的一些客户端
框架是这样的
别的接口发送数据给我的服务器
但是该数据有可能比较大,比如可能有10000个字符,(我们接收的数据全是ascii)
我在实现接收的时候,该怎么做,只使用recv()就可以了么?
这样好像有很多数据接收不到?
有人说发送的时候将那10000个字符分开来发,但是与我们相连的接口协议中并没有标示
其在发送数据的时候将大数据拆分来发
请问我该怎么做?
谢谢 因为没有细节信息,我只能猜测你们的实际情况,以此来发表看法。
1、你的软件既是服务器又是客户端?还是一个服务器程序,需要服务自己的客户端和外面公司的机器,你没写清楚。
2、用TCP传输数据,最好自定义一下头部信息,比如一次传输数据的长度、结束信息等等,解析起来容易。如果没法定义,只能循环收取了。不管发送的数据有多少字节,你只管每次收取一点,如4K,循环收取并且存储、处理即可。
3、没有数据收不到的情况,TCP已经保证了可靠性。 是这样的,其实,我自己的服务器也紧紧是一个转发的机能
并没有其他的功能
是使用完成端口做的
问题是,现在的其他公司做的接口在发送数据的时候,其TCP的数据没有明确的定义数据头相关信息
而且,在使用完成端口中,我不知道该怎么样进行循环接收数据
我按照标准的完成端口机制,在工作线程中使用GetQueuedCompletionStatus,得到缓冲区的字节数
然后读取,并根据重叠数据的结构,进行相关处理,发送下一个wsarecv
工作线程的代码如下
DWORD WINAPI WorkThread(LPVOID lpParam)
{
DWORD BytesTransferred;
CClientContext* pPerHandleData = NULL;
LPPER_IO_OPERATION_DATA pPerIoData = NULL;
int nResult;
while(TRUE)
{
if (GetQueuedCompletionStatus(g_hIOCompletionPort, &BytesTransferred,
(LPDWORD)&pPerHandleData, (LPOVERLAPPED *) &pPerIoData, INFINITE) == 0)
{
char strErr;
wsprintf(strErr, "GetQueuedCompletionStatus failed with error %d",GetLastError());
WriteDebugInfo(strErr);
RemoveFromClientListAndFreeMemory(pPerHandleData);
GlobalFree(pPerIoData);
return 0;
}
// First check to see if an error has occured on the socket and if so
// then close the socket and cleanup the SOCKET_INFORMATION structure
// associated with the socket.
if (BytesTransferred == 0)
{
if (closesocket(pPerHandleData->GetSocket()) == SOCKET_ERROR)
{
char strErr;
wsprintf(strErr, "closesocket() failed with error %d",WSAGetLastError());
WriteDebugInfo(strErr);
RemoveFromClientListAndFreeMemory(pPerHandleData);
GlobalFree(pPerIoData);
return 0;
}
RemoveFromClientListAndFreeMemory(pPerHandleData);
GlobalFree(pPerIoData);
continue;
}
switch(pPerIoData->oper)
{
case SVR_IO_WRITE:
ZeroMemory(pPerIoData,sizeof(PER_IO_OPERATION_DATA));
pPerIoData->Overlapped.hEvent = NULL;
pPerIoData->Overlapped.Internal = 0;
pPerIoData->Overlapped.InternalHigh = 0;
pPerIoData->Overlapped.Offset = 0;
pPerIoData->Overlapped.OffsetHigh = 0;
pPerIoData->DataBuf.buf = (char*)&(pPerIoData->Buffer);
pPerIoData->DataBuf.len = DATA_BUFSIZE;
pPerIoData->oper = SVR_IO_READ;
pPerIoData->flags = 0;
char strTmpB;
wsprintf(strTmpB,"before recv+++++++++++++%s",pPerIoData->Buffer);
WriteDebugInfo(strTmpB,1);
nResult = WSARecv(pPerHandleData->GetSocket(), &(pPerIoData->DataBuf),1,NULL,&(pPerIoData->flags),&(pPerIoData->Overlapped),NULL);
char strTmp;
wsprintf(strTmp,"after recv______________%s",pPerIoData->Buffer);
WriteDebugInfo(strTmp,1);
if((nResult == SOCKET_ERROR) && (WSAGetLastError() != ERROR_IO_PENDING))
{
WriteDebugInfo("WSARecv Error\n");
RemoveFromClientListAndFreeMemory(pPerHandleData);
GlobalFree(pPerIoData);
}
break;
case SVR_IO_READ:
{
pPerIoData->DataBuf.len = BytesTransferred;
pPerIoData->oper = SVR_IO_WRITE;
pPerIoData->flags = 0;
if((nResult == SOCKET_ERROR) &&
(WSAGetLastError() != ERROR_IO_PENDING))
{
WriteDebugInfo("WSASend ERROR\n");
RemoveFromClientListAndFreeMemory(pPerHandleData);
GlobalFree(pPerIoData);
}
char strTmp;
wsprintf(strTmp,"___________________________%s\n\n\n",pPerIoData->DataBuf.buf);
// WriteDebugInfo(pPerIoData->DataBuf.buf);
WriteDebugInfo(strTmp);
//................
// char ss[] = "123456789";
// send(pPerHandleData->GetSocket(),ss,sizeof(ss),0);
SendNextRequest( pPerIoData,pPerHandleData);
}
break;
default:
break;
}
}
return 1;
}
void SendNextRequest(LPPER_IO_OPERATION_DATA lpPerIOData, CClientContext* pClientContext)
{
ZeroMemory(lpPerIOData,sizeof(PER_IO_OPERATION_DATA));
lpPerIOData->Overlapped.hEvent = NULL;
lpPerIOData->Overlapped.Internal = 0;
lpPerIOData->Overlapped.InternalHigh = 0;
lpPerIOData->Overlapped.Offset = 0;
lpPerIOData->Overlapped.OffsetHigh = 0;
lpPerIOData->DataBuf.buf = (char*)&(lpPerIOData->Buffer);
lpPerIOData->DataBuf.len = DATA_BUFSIZE;
lpPerIOData->oper = SVR_IO_READ;
lpPerIOData->flags = 0;
int nResult = WSARecv(pClientContext->GetSocket(),&(lpPerIOData->DataBuf),1,NULL,
&(lpPerIOData->flags),&(lpPerIOData->Overlapped),NULL);
if((nResult == SOCKET_ERROR) && (WSAGetLastError() != ERROR_IO_PENDING))
{
WriteDebugInfo("WSARecv Error in SendNextRequest",1);
RemoveFromClientListAndFreeMemory(pClientContext);
GlobalFree(lpPerIOData);
}
// WriteDebugInfo("&&&&&&&&&&&&&&&&&&&&&&&&&");
// char strTmp;
// wsprintf(strTmp,"!!!!!!!!!!!!!!!!!!!!!!!!%s",lpPerIOData->DataBuf.buf);
// WriteDebugInfo(strTmp,1);
}
劳驾了,棒忙看看吧 思路我觉得没错啊。
所谓循环收取并转发,就是WSARecv后,处理数据,并且再次投递一次异步的WSARecv操作,仅此而已。
至于没有结束标志,那也没关系了,只管收取,在不出错误的情况下,收取一次,投递一次异步操作,直到完成为止。 先谢了
问题是,我需要获得别人发送的完整的大数据
比如别人发送的是10000个字符
我需要将这10000个字符完整的得到
然后再进行下一步操作该数据
这我该怎么实现呢?
而且,当网络繁忙的时候,完成端口中的多线程都在等待WSARecv,会不会出现这样的情况
线程1正循环接收一个10000的字符串A,在接收了8000个的时候,另一个字符串B发送过来
这时还是线程1来处理字符串B,那么最后我该怎么样整理这些字符串A和字符串B
谢谢 如果没有长度标志,你无法知道对方给你发送了多少字节,只有结束通讯后才能统计出来。所以,第一个问题无解。你能做的,就是在socket没有断开的时候,一直收取并转发数据。
第二个问题,你可以在重叠数据结构里面,加上收取的序列号码和对应的句柄数据,就能做数据的区分和对应了。
本站有个完成端口模型的框架代码,里面展示的技巧很清晰。
页:
[1]