IOCP客户端ConnectEx,GetQueuedCompletionStatus返回52错误

sky198822 2012-03-22 11:08:12
一个IOCP的程序,因为有转发功能,所以IOCP的服务端和客户端封装在同一个程序模块中,做为客户端,采用ConnectEx来做连接。做压力测试,上一级客户端并发2000个连接到这个IOCP程序,IOCP服务端收到数据后利用本程序的IOCP客户端转发数据到下一级服务器,在做大并发时,ConnectEx操作投递时能够正确返回,但是从GetQueuedCompletionStatus获取结果时返回错误,错误码52:ERROR_DUP_NAME(由于网络上有重名,没有连接。请到“控制面板”中的“系统”更改计算机名,然后重试。)
这个问题在大并发时并不是每个连接都会出现此错误,但是出现的几率也不小。以下是ConnectEx处的代码:

SOCKET ClientSocket = INVALID_SOCKET;
ClientSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_IP,
NULL, 0, WSA_FLAG_OVERLAPPED);
if (INVALID_SOCKET == ClientSocket)
{
cout << "WSASocket() failed: " << WSAGetLastError() << endl;
WSACleanup();
return FALSE;
}

SOCKADDR_IN local;
local.sin_family = AF_INET;
local.sin_addr.S_un.S_addr = INADDR_ANY;
local.sin_port = 0;
if(SOCKET_ERROR == bind(ClientSocket, (LPSOCKADDR)&local, sizeof(local)))
{
int iError = GetLastError();
printf("绑定套接字失败! %d \r\n",iError);
getchar();
return FALSE;
}

PER_IO_CONTEXT *pmyoverlapped = (PPER_IO_CONTEXT)HeapAlloc(\
GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PER_IO_CONTEXT)); // socket 和I/O 通讯的载体
pmyoverlapped ->IoOperation = IoConnect ; // 设置请求类型,得到I/O 结果时根据此来识别请求类型
pmyoverlapped ->sClient = ClientSocket;
pmyoverlapped ->pNext = NULL;

//
//为监听套接字分配一个单句柄数据
//
PPER_HANDLE_CONTEXT lpListenHandleContext = NULL;
lpListenHandleContext = (PPER_HANDLE_CONTEXT)HeapAlloc(
GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(PER_HANDLE_CONTEXT)
);
if (NULL == lpListenHandleContext)
{
closesocket(ClientSocket);
WSACleanup();
cout << "HeapAlloc() failed " << endl;
return FALSE;
}

lpListenHandleContext->IoSocket = ClientSocket;
lpListenHandleContext->pNext = NULL;

//
//将监听套接字m_ListenSocket和已经建立的完成端口关联起来
//
HANDLE hrc = CreateIoCompletionPort(
(HANDLE)ClientSocket,
m_hCOP,
(ULONG_PTR)lpListenHandleContext,
0
);
if (NULL == hrc)
{
closesocket(ClientSocket);
HeapFree(GetProcessHeap(), 0, lpListenHandleContext);
WSACleanup();

cout << "CreateIoCompletionPort failed: " << GetLastError() << endl;

return FALSE;
}

int nLen = sizeof (addrPeer );
PVOID lpSendBuffer = NULL;
DWORD dwSendDataLength = 0;
DWORD dwBytesSent = 0;

// 重点
BOOL bResult = lpConnectEx (ClientSocket ,
(sockaddr *)&addrPeer , // [in] 对方地址
nLen , // [in] 对方地址长度
lpSendBuffer , // [in] 连接后要发送的内容,这里不用
dwSendDataLength , // [in] 发送内容的字节数 ,这里不用
&dwBytesSent , // [out] 发送了多少个字节,这里不用
(OVERLAPPED *)pmyoverlapped ); // [in] 这东西复杂,下一篇有详解

int ret = WSAGetLastError ();
if (!bResult ) // 返回值处理
{
if ( WSAGetLastError () != ERROR_IO_PENDING ) // 调用失败
{
printf (TEXT ("ConnextEx error: %d\n" ),ret);
return FALSE ;
}
else // 操作未决(正在进行中 … )
{
// printf ("WSAGetLastError() == ERROR_IO_PENDING\n" );// 操作正在进行中
}
}
...全文
426 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
yzhlinux 2012-04-06
  • 打赏
  • 举报
回复
你是不是客户端也是端口回收使用的?
客户端的端口也回收使用的话会导致整个问题,要在ConnectEx 之前等上一段时间
sky198822 2012-03-24
  • 打赏
  • 举报
回复
经WSAGetOverlappedResult获取socket操作结果,10048(通常每个套接字地址(协议/网络地址/端口)只允许使用一次),由于系统存在太多TIME_WAIT状态,端口资源耗尽,所以产生52错误。
sky198822 2012-03-22
  • 打赏
  • 举报
回复
当IOCP做为客户端返回52错误的同时,对方做为被连接的服务端收不到任何消息(包括AcceptEx的GetQueuedCompletionStatus返回错误),对方的服务端也是IOCP设计,采用AcceptEx预先投递几十个接受连接。
zhanshen2891 2012-03-22
  • 打赏
  • 举报
回复
没遇到过你这个问题,你把监听的队列改小一点试试

比如改为5

18,356

社区成员

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

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