读书人

IOCP怎么获知某个客户端退出并删除该

发布时间: 2012-10-21 09:00:07 作者: rapoo

IOCP如何获知某个客户端退出,并删除该客户端?
单机测试时 有两种情况。
有时一个客户端退出后,服务器当机,停止收发数据,新客户连接不上。
除此之外就是客户端退出后,比如有3个客户端,一个退出后还是显示3个客户端,并未删除退出客户。应该在哪里删除退出客户socket?
服务部分代码:(客户端的代码就是两个线程,一个不停收,一个不停发。)

C/C++ code
    GetSystemInfo(&SystemInfo);       printf("CPU number : %d ...\n",SystemInfo.dwNumberOfProcessors);     for(i   =   0;   i   <   SystemInfo.dwNumberOfProcessors   *   2;   i++)       {           HANDLE   ThreadHandle;           //   创建一个服务器工作者线程并通过完成端口连接它。;        if   ((ThreadHandle   =   CreateThread(NULL,   0,   ServerWorkerThread,   CompletionPort,   0,   &ThreadID))   ==   NULL)           {               printf("CreateThread()   failed   with   error   %d\n",   GetLastError());               return;           }   printf_s("CreateThread %d the end ... Enter Thread %d ...\n",i+1,i+1);         //    cout<<"CreateThread "<<i+1 <<" the end ... Enter Thread " <<i+1 <<" ...\n";                 CloseHandle(ThreadHandle);   //   Close   the   thread   handle      }       //   Create   a   listening   socket       if   ((Listen   =   WSASocket(AF_INET,   SOCK_STREAM,   0,   NULL,   0,   WSA_FLAG_OVERLAPPED))   ==   INVALID_SOCKET)       {           printf("WSASocket()   failed   with   error   %d\n",   WSAGetLastError());           return;       }   printf("WSASocket the end ...\n");           InternetAddr.sin_family   =   AF_INET;           InternetAddr.sin_addr.s_addr   =   htonl(INADDR_ANY);           InternetAddr.sin_port   =   htons(PORT);       if   (bind(Listen,   (PSOCKADDR)   &InternetAddr,   sizeof(InternetAddr))   ==   SOCKET_ERROR)       {           printf("bind()   failed   with   error   %d\n",   WSAGetLastError());           return;       }   printf("Bind the end ...\n");    //   Prepare   socket   for   listening       if   (listen(Listen,   5)   ==   SOCKET_ERROR)       {           printf("listen()   failed   with   error   %d\n",   WSAGetLastError());           return;       }   printf("Listen the end ...\nEnter the loop ...\n");    while(TRUE)       {   //    接受连接并分配该完成端口。;        if   ((Accept   =   WSAAccept(Listen,   NULL,   NULL,   NULL,   0))   ==   SOCKET_ERROR)           {               printf("WSAAccept()   failed   with   error   %d\n",   WSAGetLastError());               return;           }   printf("WSAAccept Loop ...\n");                 //   Create   a   socket   information   structure   to   associate   with   the   socket           if   ((PerHandleData   =   (LPPER_HANDLE_DATA)   GlobalAlloc(GPTR,    sizeof(PER_HANDLE_DATA)))   ==   NULL)           {   printf("GlobalAlloc()   failed   with   error   %d\n",   GetLastError());               return;           }           //  accept原始完成端口socket;        printf("Socket   number   %d   connected\n",   Accept);           PerHandleData->Socket   =   Accept;           accept_socket_number.push_back(Accept) ;// 添加新客户到LIST中 ;        //将新套接字关联到IOCP上 ;        if   (CreateIoCompletionPort((HANDLE)Accept,   CompletionPort,   (DWORD)   PerHandleData,     0)   ==   NULL)           {   printf("CreateIoCompletionPort   failed   with   error   %d\n",   GetLastError());               return;           }   printf("Set CreateIoCompletionPort end...\n");         //   Create   per   I/O   socket   information   structure   to   associate   with   the   WSARecv   call   below.           if   ((PerIoData   =   (LPPER_IO_OPERATION_DATA)  GlobalAlloc(GPTR,  sizeof(PER_IO_OPERATION_DATA) ) )   ==   NULL)           {   printf("GlobalAlloc()   failed   with   error   %d\n",   GetLastError());               return;           }           ZeroMemory(&(PerIoData->Overlapped),   sizeof(OVERLAPPED));           PerIoData->BytesSEND   =   0;           PerIoData->BytesRECV   =   0;           PerIoData->DataBuf.len   =   DATA_BUFSIZE;   //初始化长度 ;        PerIoData->DataBuf.buf   =   PerIoData->Buffer;   //初始化大小 ;        Flags   =   0;           if   (WSARecv(Accept,  &(PerIoData->DataBuf),  1,  &RecvBytes,  &Flags,  &(PerIoData->Overlapped),   NULL)   ==   SOCKET_ERROR)           {               if   (WSAGetLastError()   !=   ERROR_IO_PENDING)               {   printf("WSARecv()   failed   with   error   %d\n",   WSAGetLastError());                   return;               }           }                       struct   sockaddr_in   esa;              int   esalen   =   sizeof(esa);              if(!getpeername(Accept,   (struct   sockaddr   *)&esa,   &esalen))              {      printf( " New client IP:%s ",     inet_ntoa(esa.sin_addr));                  printf( " New client PORT:%d \n",   ntohs(esa.sin_port));              }  



[解决办法]
InitializeCriticalSection(&m_section);//初始化临界区 ;
EnterCriticalSection(&m_section);//进入临界区 ;


---
这代码毫无意义。

[解决办法]
探讨

引用:
InitializeCriticalSection(&m_section);//初始化临界区 ;
EnterCriticalSection(&m_section);//进入临界区 ;
---
这代码毫无意义。

的确,可是我加这段代码之前就有同样的问题,到底该如何像客户端发送广播了,求教

[解决办法]
正确地使用锁。起码你要将m_section初始化,并在线程使用它之前(不是进入线程里)。
[解决办法]
探讨

的确,可是我加这段代码之前就有同……

[解决办法]
做IOCP用BindIoCompletionCallback简单
[解决办法]
已回答在:
http://topic.csdn.net/u/20111024/11/9e5180b4-9590-4ee0-9312-778c48be81a0.html?seed=2035811007&r=76142424#r_76142424
[解决办法]
http://blog.csdn.net/visualeleven/article/details/6088590

读书人网 >VC/MFC

热点推荐