VC IOCP 为什么只支持几百个连接

wxliangzyt 2013-11-13 07:53:13
启动IOCP的函数,(默认创建100个,不够时在自动创建,上限为1W)

BOOL CIOCPServer::Startselfserver(UINT uListenPort)
{
if (!WinSockInit())
{
return FALSE;
}
m_ListenSocket = WSASocket(AF_INET , SOCK_STREAM , IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
if ( m_ListenSocket == INVALID_SOCKET )
{
goto __Error_End;
}
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = INADDR_ANY;
service.sin_port = htons(uListenPort);
if ( bind(m_ListenSocket, (sockaddr*)&service, sizeof(sockaddr_in)) == SOCKET_ERROR )
{
goto __Error_End;
}
if( listen(m_ListenSocket, SOMAXCONN) == SOCKET_ERROR )
{
SetLastErrorMsg(_T("监听失败!"));
goto __Error_End;
}
m_hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
if ( m_hCompletionPort == NULL )
{
SetLastErrorMsg(_T("完成端口创建失败!"));
goto __Error_End;
}
CreateIoCompletionPort((HANDLE)m_ListenSocket, m_hCompletionPort,(ULONG_PTR)m_ListenSocket, 0);
m_wsaapi.LoadAllFun(m_ListenSocket);
::InitializeCriticalSection(&m_getsktpoll);
SYSTEM_INFO systeminfo;
GetSystemInfo(&systeminfo);
pThreadpool = CreateThreadpool(NULL);
SetThreadpoolThreadMinimum(pThreadpool, 2);
SetThreadpoolThreadMaximum(pThreadpool,(int)systeminfo.dwNumberOfProcessors *2);
InitializeThreadpoolEnvironment(&tcbe);
SetThreadpoolCallbackPool(&tcbe, pThreadpool);
pTpcg= CreateThreadpoolCleanupGroup();
SetThreadpoolCallbackCleanupGroup(&tcbe, pTpcg, NULL);
pTpWork= CreateThreadpoolWork(allMyWorkCallback,this,&tcbe);
SubmitThreadpoolWork(pTpWork);
///先投递100的等连接
PostCreateSocket(m_ListenSocket);//创建一个SOCKET池
return TRUE;

创建一个SOCKET池的代码如下:

BOOL CIOCPServer::PostCreateSocket(SOCKET cListSKT)
{
SOCKET cClientSKT;
CSoketpool *cspl=NULL;
int lierr=0;
int li=0;
for (li=0;li<m_ConnFreeMax;li++)
{
cClientSKT=WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,0,WSA_FLAG_OVERLAPPED);
if (INVALID_SOCKET == cClientSKT)
{
lierr=WSAGetLastError();
break;
}
CreateIoCompletionPort((HANDLE)cClientSKT,m_hCompletionPort,(ULONG_PTR)cListSKT,0);
COverLappedEx *m_pOverLap = new COverLappedEx(IO_TYPE_ACCEPT,cClientSKT);
BOOL bRet = AcceptEx(cListSKT,cClientSKT, m_pOverLap->m_szBuf, 0,
sizeof(sockaddr_in)+16, sizeof(sockaddr_in)+16, &m_pOverLap->dwBytesRecv, &m_pOverLap->m_OLap);
if (!bRet)
{
if (WSAGetLastError() != WSA_IO_PENDING)
{
AfxMessageBox(_T("111"));
break;
}
}
InterlockedIncrement(&m_ConnSKTCount);
InterlockedIncrement(&m_ConnNowCount);
}
BOOL lspw=SetProcessWorkingSetSize(GetCurrentProcess(),1024*1024*1024,2*1024*1024*1024);
return TRUE;
}


IOCP工作函数


VOID CALLBACK allMyWorkCallback(PTP_CALLBACK_INSTANCE Instance,PVOID Parameter,PTP_WORK Work)
{
//接收DLL的主线程
CIOCPServer *pThis = (CIOCPServer *)Parameter;
COverLappedEx *pOverLaps = NULL;
SOCKET cListenSKT;
BOOL bIORet=FALSE;
BOOL bSendt=FALSE;
DWORD dwTrans = 0;
char lctype=NULL;
char revc[2048]={0};
CString csket;
char szx[10] = {'\0'};
PTP_WORK pTpWorks;
DWORD dwFlags=0;

InterlockedIncrement(&pThis->m_ThreadNums);
while (TRUE)
{
bIORet = GetQueuedCompletionStatus(pThis->m_hCompletionPort, &dwTrans, (PULONG_PTR)&cListenSKT, (LPOVERLAPPED *)&pOverLaps, INFINITE);
if (!bIORet) continue;
if(bIORet && pOverLaps)
{
switch (pOverLaps->m_IOType)
{
case IO_TYPE_READ:
{
memset(revc,0,2048);
WSABUF wsaBuf = {0};
wsaBuf.buf = revc;
wsaBuf.len = 2048;

WSARecv(pOverLaps->m_ClientSKT, &wsaBuf, 1, &(pOverLaps->dwBytesRecv), &(pOverLaps->dwFlags), NULL, NULL);
if ((strcmp(revc,"")==0) || (revc[0]==NULL))
{//接收到空数据,断开连接
pThis->PostCloseSocket(pOverLaps->m_ClientSKT,pOverLaps);
pThis->Postaccept(pOverLaps);//断开连接后,重新投递为连接请求
continue;
}
memset(revc,0,2048);
pThis->PostRecv(pOverLaps);
continue;
}
case IO_TYPE_SEND:
{
continue;
}
case IO_TYPE_ACCEPT:
{ InterlockedDecrement(&pThis->m_ConnSKTCount);

pThis->PostRecv(pOverLaps);
pTpWorks= CreateThreadpoolWork(allMyWorkCallback,pThis,&pThis->tcbe);// 创建一个工作项
SubmitThreadpoolWork(pTpWorks);
if (pThis->m_ConnSKTCount<pThis->m_ConnFreeMax)
{
pThis->PostCreateSocket(cListenSKT);
}
continue;
}
case IO_TYPE_CLOSE:
{
continue;
}
default:
{
continue;
}
}
}
else if (!pOverLaps )
{
break;
}
}
InterlockedDecrement(&pThis->m_ThreadNums);
return ;
}


PostRecv投递函数

BOOL CIOCPServer::PostRecv(COverLappedEx *m_pOverLap)
{
ZeroMemory(&(m_pOverLap->m_OLap), sizeof(OVERLAPPED));
m_pOverLap->m_IOType=IO_TYPE_READ;
m_pOverLap->dwBytesRecv=0;
WSABUF wsaBuf={NULL,0};
int iRet = WSARecv(m_pOverLap->m_ClientSKT,&wsaBuf, 1, &(m_pOverLap->dwBytesRecv), &(m_pOverLap->dwFlags), &(m_pOverLap->m_OLap), NULL);
if (iRet != NO_ERROR)
{
int lierr=WSAGetLastError() ;
if (lierr != WSA_IO_PENDING)
{
delete m_pOverLap;
return FALSE;
}
}
return TRUE;
}

COverLappedEx结构体


class COverLappedEx
{
public:
OVERLAPPED m_OLap;
IO_TYPE m_IOType;
char m_szBuf[100];
DWORD dwBytesRecv,dwFlags;
SOCKET m_ClientSKT;//客户端连接的IP

COverLappedEx(IO_TYPE ioType,SOCKET cskt)
{
ZeroMemory(&m_OLap, sizeof(OVERLAPPED));
memset(m_szBuf,0,100);
m_IOType = ioType;
dwBytesRecv=0;
dwFlags=0;
m_ClientSKT=cskt;
}
};


主要代码就是这个样子,现在的问题是:
1:如果IOCP,我注释掉PostRecv函数,只让服务器接受客户端的连接,那么可以连5000个左右。
2:不注释掉PostRecv函数,那么能连接1000多个
3:如果我还把postsend函数开启,连接数就更少了(这个我没贴出来)

求高人指点,
本人QQ:38200180,高手能远程协助就更好了,

测试IOCP能连接多少客户端的代码如下:

int li=1;
WSADATA data = {0};
char buf[1024];
if(WSAStartup(MAKEWORD(2, 2), &data))
return ;
if ( LOBYTE(data.wVersion) !=2 || HIBYTE(data.wVersion) != 2 )
{
WSACleanup();
return ;
}
while (true)
{
Sleep(10);
/* if (li>=8000)
{
int lix=0;
lix=9;
break;
}*/
m_Socket[li] = socket(AF_INET , SOCK_STREAM , IPPROTO_TCP);
sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(999);
server.sin_addr.s_addr = inet_addr("125.84.184.223");

int lict=connect(m_Socket[li], (struct sockaddr *)&server, sizeof(struct sockaddr));
if (lict == SOCKET_ERROR )
{
DWORD Serrs= WSAGetLastError();

CString cs;
cs.Format(_T("%d:%d"),li,Serrs);
AfxMessageBox(cs);
WSACleanup();
return ;
}
...全文
524 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
fishion 2013-11-22
  • 打赏
  • 举报
回复
再看了下,原来你是想用0空间异步的方式触发recv,然后再用同步的方式接收数据
fishion 2013-11-22
  • 打赏
  • 举报
回复
wsaBuf.buf = revc; 多个不同的套节字连接后需要接收时你却给套节字一个地址重复的指针给套节字接收数据? 你最好还是一个COverLappedEx带一一段独立的revc内存空间,然后再把这段空间指定给wsaBuf.buf 就连接数来说的话,只连接而不接收发送数据那很容易就能超过1W个
xzben 2013-11-22
  • 打赏
  • 举报
回复
引用 11 楼 wxliangzyt 的回复:
楼上的,技术差,
。。。。。。。
wxliangzyt 2013-11-21
  • 打赏
  • 举报
回复
我顶顶我顶顶我顶顶
wxliangzyt 2013-11-20
  • 打赏
  • 举报
回复
我顶顶我顶顶我顶顶我顶顶我顶顶我顶顶我顶顶我顶顶我顶顶我顶顶
wxliangzyt 2013-11-19
  • 打赏
  • 举报
回复
楼上的,技术差,
版主大哥 2013-11-19
  • 打赏
  • 举报
回复
accept 就别用异步了,用同步省事...
wxliangzyt 2013-11-18
  • 打赏
  • 举报
回复
我顶上去,我顶上去,我顶上去,我顶上去
xzben 2013-11-18
  • 打赏
  • 举报
回复
你为什么不在收到一个连接之后在投递一个accpet呢!投这么多干嘛! 菜鸟自己写了一个小东西使用的就是IOCP欢迎围观 https://github.com/xzben/xzben
版主大哥 2013-11-17
  • 打赏
  • 举报
回复
QQ还要回答问题 =。=!
wxliangzyt 2013-11-17
  • 打赏
  • 举报
回复
我顶上去,我顶上去,我顶上去,我顶上去,
wxliangzyt 2013-11-17
  • 打赏
  • 举报
回复
我顶上去,我顶上去,我顶上去,我顶上去
wxliangzyt 2013-11-16
  • 打赏
  • 举报
回复
我顶上去,我顶上去,我顶上去,我顶上去,
wxliangzyt 2013-11-14
  • 打赏
  • 举报
回复
IOCP投递了很多空间的连接,客户端connect时,返回10060
许文君 2013-11-14
  • 打赏
  • 举报
回复
connect不上了还是怎么的?
yaozhiyong110 2013-11-14
  • 打赏
  • 举报
回复
客户端也没看你发数据 还有你说的连接数变少 是旧连接被断开了还是新连接连不上?

18,356

社区成员

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

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