首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VC/MFC >

IOCP突然理解不了了,这是一段很基础的IOCP代码,是有回显功能的(WSASEND),哪位高手俩帮小弟我把WSASEND去掉

2012-10-21 
IOCP突然理解不了了,这是一段很基础的IOCP代码,是有回显功能的(WSASEND),谁俩帮我把WSASEND去掉。#include

IOCP突然理解不了了,这是一段很基础的IOCP代码,是有回显功能的(WSASEND),谁俩帮我把WSASEND去掉。
#include <winsock2.h> 
#include <windows.h> 
#include <stdio.h> 
#pragma comment(lib,"Ws2_32.lib")
#define PORT 5000
#define DATA_BUFSIZE 8192 

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; 
printf("服务器准备好,等待接入客户端:\n");
  if ((Ret = WSAStartup(0x0202, &wsaData)) != 0) 
  { 
  printf("WSAStartup failed with error %d\n", Ret); 
  return; 
  } 

  // Setup an I/O completion port. 

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

  // Create worker threads based on the number of processors available on the 
  // system. Create two worker threads for each processor. 

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

  } 

  // 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; 
  }  

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

  // Prepare socket for listening 

  if (listen(Listen, 5) == SOCKET_ERROR) 
  { 


  printf("listen() failed with error %d\n", WSAGetLastError()); 
  return; 
  } 

  // Accept connections and assign to the completion port. 

  while(TRUE) 
  { 
  if ((Accept = WSAAccept(Listen, NULL, NULL, NULL, 0)) == SOCKET_ERROR) 
  { 
  printf("WSAAccept() failed with error %d\n", WSAGetLastError()); 
  return; 
  } 

  // 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; 
  } 

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

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

  if (CreateIoCompletionPort((HANDLE) Accept, CompletionPort, (DWORD) PerHandleData, 
  0) == NULL) 
  { 
  printf("CreateIoCompletionPort failed with error %d\n", GetLastError()); 
  return; 
  } 

  // 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; 
  } 
  } 
  } 


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) 
  { 
   
  if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred, 
  (LPDWORD)&PerHandleData, (LPOVERLAPPED *) &PerIoData, INFINITE) == 0) 
  { 
  printf("GetQueuedCompletionStatus failed with error %d\n", GetLastError()); 
  return 0; 
  } 


  // First check to see if an error has occured on the socket and if so 
  // then close the socket and cleanup the SOCKET_INFORMATION structure 


  // associated with the socket. 

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

  // Check to see if the BytesRECV field equals zero. If this is so, then 
  // this means a WSARecv call just completed so update the BytesRECV field 
  // with the BytesTransferred value from the completed WSARecv() call. 

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


我一删WSASend(),就接收不了新的信息了。怎么回事。。。求大神帮改。。

[解决办法]
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;
}
}
}
以上删除,保留如下代码:
 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;
}
}

热点排行