一个完成端口的问题,帮忙看一下问题出在那,谢谢
下面这个是完成端口的工作线程,收到客户端的数据后,又原封不动的发回客户端,可怎么也发不回去呀,收没问题!
1、大家帮忙看看,问题出在什么地方!怎么改才能成功投递一个WSASend()操作呀!
2、还有就是完成键的怎样定义才合适(既要发数据,又要收数据),GetQueuedCompletionStatus()返回后是怎么修改这个完成键的!
//工作线程用到的数据结构
#define RECV_POSTED 1
#define SEND_POSTED 2
typedef struct
{
SOCKET sock;
}PER_HANDLE_DATA,*LPPER_HANDLE_DATA;
typedef struct
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
DWORD RecvBytes;
CHAR Buffer[DATA_BUFSIZE];
UINT OperationType; //1=RECV_POSTED 2=SEND_POSTED
}PER_IO_OPERATION_DATA,*LPPER_IO_OPERATION_DATA;
//工作线程如下:
UINT IOCPThread(LPVOID lParam)
{
COverlappedDlg *pDlg=(COverlappedDlg *)lParam;
DWORD BytesTransferred;
// OVERLAPPED Overlapped;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_OPERATION_DATA PerIoData;
DWORD SendBytes,RecvBytes;
DWORD Flags;
try
{
while(TRUE)
{
if(GetQueuedCompletionStatus(pDlg->m_CompletionPort,&BytesTransferred,(LPDWORD)&PerHandleData,(LPOVERLAPPED
*)&PerIoData,INFINITE)==0)
{
TRACE("\nGetQueuedCompletionStatus() is Error ......");
return 0;
}
if(BytesTransferred==0)
{
TRACE("\n关闭了一个SOCKET");
closesocket(PerHandleData->sock);
GlobalFree(PerHandleData);
GlobalFree(PerIoData);
continue;
}
if(PerIoData->OperationType==RECV_POSTED)
{
PerIoData->RecvBytes = BytesTransferred;
Flags = 0;
ZeroMemory(&(PerIoData->Overlapped),sizeof(OVERLAPPED));
PerIoData->OperationType = SEND_POSTED;
PerIoData->DataBuf.len=BytesTransferred;
WSASend(PerHandleData->sock,(LPWSABUF)&PerIoData->DataBuf,1,&SendBytes,Flags,&(PerIoData->Overlapped),NULL);
pDlg->PostMessage(WM_RECVDATA,0,(LPARAM)PerIoData->Buffer);
Flags = 0;
ZeroMemory(&(PerIoData->Overlapped),sizeof(OVERLAPPED));
PerIoData->DataBuf.len = DATA_BUFSIZE;
PerIoData->DataBuf.buf = PerIoData->Buffer;
PerIoData->OperationType = RECV_POSTED;
WSARecv(PerHandleData->sock,&(PerIoData->DataBuf),1,&RecvBytes,&Flags,&(PerIoData->Overlapped),NULL);
}
if(PerIoData->OperationType==SEND_POSTED)
{
TRACE("\n发送数据成功");
}
}
}
catch(...)
{
TRACE("\n出错了!一个IOCPThread结束了......");
return 0;
}
TRACE("\n一个IOCPThread结束了......");
return 0;
}
问题点数:100、回复次数:18Top
1 楼phiger(phiger)回复于 2004-07-03 13:48:08 得分 27
if(PerIoData->OperationType==SEND_POSTED)
{
TRACE("\n发送数据成功");
}
这段代码不行,收到发送的事件通知并不意味着发送数据完成了,因为你是异步的,可能只发送成功了一部分
大概改成
if(PerIoData->OperationType==SEND_POSTED)
{
if (BytesTransferred < PerIoData->DataBuf.len)
{ // 没发送完继续发送
PerIoData->DataBuf.buf += BytesTransferred;
PerIoData->DataBuf.len -=BytesTransferred;
WSASend(PerHandleData->sock,(LPWSABUF)&PerIoData->DataBuf,1,&SendBytes,Flags,&(PerIoData->Overlapped),NULL);
}
}Top
2 楼zxs0001(盛)回复于 2004-07-03 16:12:03 得分 0
To: phiger(phiger)
1、为什么即使发送成功PerIoData->OperationType也不会等于SEND_POSTED?
if(PerIoData->OperationType==SEND_POSTED)
{
......
}
上面条件语句中的内容永远不会执行呀?
2、WSASend、WSARecv投递之前应该
Flags = 0;
ZeroMemory(&(PerIoData->Overlapped),sizeof(OVERLAPPED));
对吗?
但你上面补充的里面没有写呀?
Top
3 楼chenjieread(苦学VC++中...)回复于 2004-07-03 16:32:20 得分 2
你们 好厉害啊!!!羡慕Top
4 楼zxs0001(盛)回复于 2004-07-04 05:50:33 得分 0
大家帮忙看看呀!
1、为什么我WSASend()成功后,GetQueuedCompletionStatus()返回后PerIoData->OperationType还是等于SEND_POSTED
2、WSASend、WSARecv投递之前应该做些什么操作(对PerIoData及PerHandleData)
3、如果接收数据特别频繁(假设有20个客户端,每个客户端每秒有1000个数据到达,收到后还要应答),上面的那段代码是否还应该做适当修改才可胜任?
谢谢!Top
5 楼zxs0001(盛)回复于 2004-07-05 08:40:54 得分 0
怎么没人回答呀,是不是由于前两天是周末的原因呀!Top
6 楼Cowboy22(西部牛仔)回复于 2004-07-05 10:39:43 得分 30
if(PerIoData->OperationType==RECV_POSTED){
在这里你先是对PerIoData赋值; ... WSASend(), 紧跟着又对PerIoData赋值改写了PerIoData ...WSARecv(); 这样可能会导致出现你的问题。
}
所以建议PER_HANDLE_DATA结构应该对WSASend和WSARecv两个操作分别定义对应的Overlapped,DataBuf, RecvBytes, Buffer, OperationType:
struct IOContext{
OVERLAPPED Overlapped;
WSABUF DataBuf;
DWORD RecvBytes;
CHAR Buffer[DATA_BUFSIZE];
UINT OperationType; //1=RECV_POSTED 2=SEND_POSTED
};
struct PER_HANDLE_DATA{
SOCKET socket;
IOContext send, recv;
};Top
7 楼zxs0001(盛)回复于 2004-07-05 11:59:56 得分 0
To: Cowboy22(西部牛仔)
谢谢你的回答,我明白了
那对于我的第3个问题该怎么解决呀,像我上面的那段代码可以投入实际应用吗???万分感谢!
Top
8 楼zxs0001(盛)回复于 2004-07-05 17:34:47 得分 0
没有人关注了?????Top
9 楼zxs0001(盛)回复于 2004-07-06 12:20:09 得分 0
大家提提建议呀!!!!!Top
10 楼zxfvc(七品VC)回复于 2004-07-09 11:35:23 得分 4
我都还在迷惑中
<<windows 网络编程>>中好象还很多错呀,对于初学者来说有点不好懂。Top
11 楼zxs0001(盛)回复于 2004-07-10 15:15:30 得分 0
<<windows 网络编程>>看过了,还不是很懂呀!!!!Top
12 楼zxfvc(七品VC)回复于 2004-07-10 16:28:20 得分 0
昨天看了楼主的帖,回去做了一个程序,基本正常,但客户端只能接收到有限的内容(如果服务方发了大量的数据),可能就是上面的说的那样,没发完吧,我也不知道该怎样解决了,等高手来指点一下。Top
13 楼zxfvc(七品VC)回复于 2004-07-10 16:30:56 得分 0
请问楼主,你if(PerIoData->OperationType==RECV_POSTED)中的PerIoData->OperationType是怎样获得的?
Top
14 楼newlili(神啊,救救我吧!)回复于 2004-07-12 13:04:32 得分 2
学习ing...
等我会了,一定告诉你^_^Top
15 楼zxs0001(盛)回复于 2004-07-14 08:56:43 得分 0
To:zxfvc(七品VC)
对你说的
“请问楼主,你if(PerIoData->OperationType==RECV_POSTED)中的PerIoData->OperationType是怎样获得的?”
我也不是很清楚,改成像 Cowboy22(西部牛仔) 说的那样也许会好理解些
我也希望来个高手指点一下呀!!!Top
16 楼zxs0001(盛)回复于 2004-07-21 14:55:02 得分 0
问题没解决又有新的问题了
那位大虾,提点提点呀
判断出一个客户端断开之后,要不要清理与该客户端连接的套接字投递的操作,如果清理的话应该怎么清理!
只求提供思路就行了!
Top
17 楼ZHENG017()回复于 2004-07-21 16:00:48 得分 35
OperationType是自己指定的。
实际应用?还得继续改吧。在ms的sdk中有一个iocp的例子。
要清理,不然占用句柄数过多,程序崩溃。服务器程序最怕内存泄露,gdi,句柄泄露。Top
18 楼zxs0001(盛)回复于 2004-07-21 19:14:39 得分 0
To: ZHENG017()
能给个清理的思路吗?谢谢!!Top




