Iocp to SOCKET Communications (reprint)

  Since the choice hxzb7215191 Blog 

  Of course the model is also available in TCP mode incident choice model. 
  Is all the networking events and our definition of a procedure in the incident Bang. 
  This has its advantages, we may be able to better write a thread to manage reception and transmission. 
  Now speaking about a complete port model. 

  Port completed 

  In fact, a complete port is a queue informed by the operating system have already been completed overlapping I / O requests notice 
  Add to them.    When an I / O operation Once completed, the operation could be a result of thread processing workers 
  Will receive a notice.    And the socket is created, they can at any time with a complete port clearance 
  Together. 

  Steps: 
  1, the completion of the creation of a space port; 
  2, the local machine by the number of CPU; 
  3, open CPU * 2 of threads (also known as thread pool), are all waiting for the completion of the port completed packets; 
  4, the monitor to create TCP socket, the state will use the incident to create eavesdropping thread; 
  5, when someone entered the connection, will be kept to a Client socket our own definition of the key button, 
  And bring it with us to create a complete port association; 
  6, and the use of WSARecv WSASend function drop some requests, which is the use of overlapping I / O; 
  7, repeat 5-6; 

  Note: 1, overlapping I / O mode, the receiving and sending data packets, must request this is a drop 
  They feature of this architecture 
  Of course, the completion of port approach, is not direct use WSARecv and WSASend function request 
  The drop boxes.    Instead use the ReadFile, Write the way 
  2, the use of the port completed within the system models, so long as we must call on the order of 
  Can be completed. 
  3, complete port is used in such circumstances, there are tens of thousands of users connected, it can 
  Performance will not guarantee lower. 


  # Include <winsock2.h> 
  # Include <windows.h> 
  # Include <stdio.h> 

  # Define PORT 5150 
  # Define DATA_BUFSIZE 8192 

  / / Key items 
  Typedef struct 
  ( 
  OVERLAPPED Overlapped; 
  WSABUF DataBuf; 
  CHAR Buffer [DATA_BUFSIZE]; 
  DWORD BytesSEND; 
  DWORD BytesRECV; 
  ) PER_IO_OPERATION_DATA * LPPER_IO_OPERATION_DATA; 


  Typedef struct 
  ( 
  SOCKET Socket; 
  ) PER_HANDLE_DATA * LPPER_HANDLE_DATA; 

  DWORD WINAPI ServerWorkerThread (LPVOID CompletionPortID); 

  Void main (void) 
  ( 
  SOCKADDR_IN InternetAddr; 
  SOCKET Listen; 
  SOCKET Accept; 
  HANDLE CompletionPort; 
  SYSTEM_INFO SystemInfo; 
  LPPER_HANDLE_DATA PerHandleData; 
  LPPER_IO_OPERATION_DATA PerIoData; 
  Int i; 
  DWORD RecvBytes; 
  DWORD Flags; 
  DWORD ThreadID; 
  WSADATA wsaData; 
  DWORD Ret; 

  If ((Ret = WSAStartup (0×0202, & wsaData))! = 0) 
  ( 
  Printf ( "WSAStartup failed with error% d \ n", Ret); 
  Return; 
  ) 

  / / Open an empty port completed 

  If ((CompletionPort = CreateIoCompletionPort (INVALID_HANDLE_VALUE, NULL, 0, 0)) == NULL) 
  ( 
  Printf ( "CreateIoCompletionPort failed with error:% d \ n", GetLastError ()); 
  Return; 
  ) 

  / / Determine how many processors are on the system. 

  GetSystemInfo (& SystemInfo); 

  / / Open the cpu 2 times the number of threads 

  For (i = 0; i <SystemInfo.dwNumberOfProcessors * 2; i + +) 
  ( 
  HANDLE ThreadHandle; 

  / / Create a server worker thread and pass the completion port to the thread. 

  If ((ThreadHandle = CreateThread (NULL, 0, ServerWorkerThread, CompletionPort, 
  0, & ThreadID)) == NULL) 
  ( 
  Printf ( "CreateThread () failed with error% d \ n", GetLastError ()); 
  Return; 
  ) 

  / / Close the thread handle 
  CloseHandle (ThreadHandle); 
  ) 

  / / Open a server 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; 
  ) 

  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; 
  ) 


  If (listen (Listen, 5) == SOCKET_ERROR) 
  ( 
  Printf ( "listen () failed with error% d \ n", WSAGetLastError ()); 
  Return; 
  ) 

  / / Begin to receive from the client connections 

  While (TRUE) 
  ( 
  If ((= Accept WSAAccept (Listen, NULL, NULL, NULL, 0)) == SOCKET_ERROR) 
  ( 
  Printf ( "WSAAccept () failed with error% d \ n", WSAGetLastError ()); 
  Return; 
  ) 

  / / Create a key for the preservation of the client's information, send users to receive overlapping structure, 
  / / Used to have a buffer 
  If ((PerHandleData = (LPPER_HANDLE_DATA) GlobalAlloc (GPTR, 
  Sizeof (PER_HANDLE_DATA))) == NULL) 
  ( 
  Printf ( "GlobalAlloc () failed with error% d \ n", GetLastError ()); 
  Return; 
  ) 

  / / Associate the accepted socket with the original completion port. 

  Printf ( "% d connected Socket number \ n", Accept); 
  PerHandleData-> Socket = Accept; 

  / / And that we completed the creation of the port association, it will be critical with the completion of a designated port association 
  If (CreateIoCompletionPort ((HANDLE) Accept, CompletionPort, (DWORD) PerHandleData, 
  0) == NULL) 
  ( 
  Printf ( "CreateIoCompletionPort failed with error% d \ n", GetLastError ()); 
  Return; 
  ) 

  / / Sending a receiver, receiver need to use this function to a reception for delivery 

  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; 
  ) 
  ) 
  ) 
  ) 
  / / Work thread 
  DWORD WINAPI ServerWorkerThread (LPVOID CompletionPortID) 
  ( 
  HANDLE CompletionPort = (HANDLE) CompletionPortID; 
  DWORD BytesTransferred; 
  LPOVERLAPPED Overlapped; 
  LPPER_HANDLE_DATA PerHandleData; 
  LPPER_IO_OPERATION_DATA PerIoData; 
  DWORD SendBytes, RecvBytes; 
  DWORD Flags; 

  While (TRUE) 
  ( 
  / / Port is complete news to the 
  If (GetQueuedCompletionStatus (CompletionPort, & BytesTransferred, 
  (LPDWORD) & PerHandleData (LPOVERLAPPED *) & PerIoData, INFINITE) == 0) 
  ( 
  Printf ( "GetQueuedCompletionStatus failed with error% d \ n", GetLastError ()); 
  Return 0; 
  ) 


  / / It be that some people withdrew from the 

  If (BytesTransferred == 0) 
  ( 
  Printf ( "Closing socket% d \ n", PerHandleData-> Socket); 

  If (closesocket (PerHandleData-> Socket) == SOCKET_ERROR) 
  ( 
  Printf ( "closesocket () failed with error% d \ n", WSAGetLastError ()); 
  Return 0; 
  ) 

  GlobalFree (PerHandleData); 
  GlobalFree (PerIoData); 
  Continue; 
  ) 

  / / 

  If (PerIoData-> BytesRECV == 0) 
  ( 
  PerIoData-> BytesRECV = BytesTransferred; 
  PerIoData-> BytesSEND = 0; 
  ) 
  Else 
  ( 
  PerIoData-> BytesSEND + = BytesTransferred; 
  ) 

  If (PerIoData-> BytesRECV> PerIoData-> BytesSEND) 
  ( 

  / / Post another WSASend () request. 
  / / Since WSASend () is not gauranteed to send all of the bytes requested, 
  / / Continue posting WSASend () calls until all received bytes are sent. 

  ZeroMemory (& (PerIoData-> Overlapped), sizeof (OVERLAPPED)); 

  PerIoData-> DataBuf.buf = PerIoData-> Buffer + PerIoData-> BytesSEND; 
  PerIoData-> DataBuf.len = PerIoData-> BytesRECV - PerIoData-> BytesSEND; 

  If (WSASend (PerHandleData-> Socket, & (PerIoData-> DataBuf), 1, & SendBytes, 0, 
  & (PerIoData-> Overlapped), NULL) == SOCKET_ERROR) 
  ( 
  If (WSAGetLastError ()! = ERROR_IO_PENDING) 
  ( 
  Printf ( "WSASend () failed with error% d \ n", WSAGetLastError ()); 
  Return 0; 
  ) 
  ) 
  ) 
  Else 
  ( 
  PerIoData-> BytesRECV = 0; 

  / / Now that there are no more bytes to send post another WSARecv () request. 

  Flags = 0; 
  ZeroMemory (& (PerIoData-> Overlapped), sizeof (OVERLAPPED)); 

  PerIoData-> DataBuf.len = DATA_BUFSIZE; 
  PerIoData-> DataBuf.buf = PerIoData-> Buffer; 

  If (WSARecv (PerHandleData-> Socket, & (PerIoData-> DataBuf), 1, & RecvBytes, & Flags, 
  & (PerIoData-> Overlapped), NULL) == SOCKET_ERROR) 
  ( 
  If (WSAGetLastError ()! = ERROR_IO_PENDING) 
  ( 
  Printf ( "WSARecv () failed with error% d \ n", WSAGetLastError ()); 
  Return 0; 
  ) 
  ) 
  ) 
  ) 
  ) 

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Facebook
  • DotNetKicks
  • DZone
  • Netvouz
  • Propeller

Tags: ,

Releated Java Articles

Comments

Leave a Reply