C语言辅导:面向短连接的网络服务器

来源:计算机等级考试    发布时间:2012-08-28    计算机等级考试视频    评论

  2009年下半年全国计算机等级考试你准备好了没?考计算机等级考试的朋友,2009年下半年全国计算机等级考试时间是2009年9月19日至23日。更多优质资料尽在考试大论坛 考试大在线题库
  前几天同事用sf上的一个网络类库写了个服务器。一测试发现性能很差。最多每秒才能处理500次请求,并且是在网络很好的情况下,隔两个交换机后客户端就只能收到200次/秒的正确响应了。同事忙着做其它事,改进服务器的任务就交给我了。
  项目中客户端的请求仅是有20bytes的数据,并且只有一小部分需要服务器回复500bytes左右的数据。综合考虑各种网络模型后我决得IOCP模型更适合当前的应用。
  IOCP模型的使用方法很多资料都有。《windows网络编程》(第二版)讲得很好。随书光盘中有使用IOCP模型的简单但很好的例子。我的服务器程序写完时还没看到这个示例,正被其它示例代码里的锁弄的晕头转向。当看到这个示例后发现那些锁都是多余的。剩下的代码基本上差不多。
  有点不同的是PER_IO_DATA的处理上。所有的例子在往完成端口投递请求时都先分配了一个PER_IO_DATA,请求处理后马上释放。考虑到我的应用中所有请求全部是短连接,并且数据量很小,我觉得分配和释放是浪费的。每个PER_IO_DATA对应一个socket,当socket关闭后这个PER_IO_DATA不必释放,而是用来准备接受下一个连接socket。
  下面是写的工作线程代码:
  DWORD WINAPI ServerWorkerThread(LPVOID lpparam)
  {
  CIocpServer * pServer = (CIocpServer*)lpparam;
  DWORD BytesTransferred;
  SOCKET socket;
  LPPER_IO_OPERATION_DATA PerIoData;
  BOOL close_socket = FALSE;
  int ret;
  while(pServer->bRun)
  {
  ret = GetQueuedCompletionStatus(pServer->CompletionPort, &BytesTransferred,
  (LPDWORD)&socket, (LPOVERLAPPED *) &PerIoData, INFINITE);
  if (ret == ERROR_SUCCESS)
  {
  DWORD last_error = GetLastError();
  if(last_error == ERROR_SUCCESS)
  return 0;    //完成端口被关闭,退出
  if(ERROR_NETNAME_DELETED == last_error  
  || ERROR_OPERATION_ABORTED == last_error)
  close_socket = TRUE;    //socket被关闭 或者 操作被取消
  else
  continue;
  }
  if (BytesTransferred == 0)
  {
  if(socket == 0 && PerIoData == 0)
  break;
  closesocket(PerIoData->socket);
  pServer->Accept(PerIoData);
  continue;
  }
  if(PerIoData->eType == IO_EVENT_ACCEPT)
  {
  setsockopt(PerIoData->socket,SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char*)&(pServer->m_server), sizeof(pServer->m_server) ) ;
  if(CreateIoCompletionPort((HANDLE) PerIoData->socket, pServer->CompletionPort, (DWORD) PerIoData->socket,0) == NULL)
  printf("CreateIoCompletionPort error:%d ", GetLastError());
  ret = pServer->Recv(PerIoData,BytesTransferred);
  }
  else if(PerIoData->eType == IO_EVENT_WSARECV)
  {
  ret = pServer->Recv(PerIoData,BytesTransferred);
  }
  else if(PerIoData->eType == IO_EVENT_WSASEND)
  {
  ret = pServer->Send(PerIoData,BytesTransferred);
  }
  if(ret == FALSE)
  {
  closesocket(PerIoData->socket);
  pServer->Accept(PerIoData);
  }
  }
  return 0;
  }
  可以看到,每个AccepteEx接入的客户端连接对应着一个PER_IO_DATA,并伴随着该连接的整个生命周期。考试大提示当连接结束后,PER_IO_DATA马上又通过投递AccepteEx准备下一个连接。这样可以避免平凡的分配和释放内存。

  2009年上半年全国计算机等级考试参考答案请进入计算机考试论坛

  2009年全国计算机等级考试报名信息汇总

  2009年NCRE考试有新变化

  2009年全国计算机等级考试大纲

  2009年上半年全国计算机二级考试试题及答案

  2009年上半年全国计算机等级考试试题答案汇总

视频学习

我考网版权与免责声明

① 凡本网注明稿件来源为"原创"的所有文字、图片和音视频稿件,版权均属本网所有。任何媒体、网站或个人转载、链接转贴或以其他方式复制发表时必须注明"稿件来源:我考网",违者本网将依法追究责任;

② 本网部分稿件来源于网络,任何单位或个人认为我考网发布的内容可能涉嫌侵犯其合法权益,应该及时向我考网书面反馈,并提供身份证明、权属证明及详细侵权情况证明,我考网在收到上述法律文件后,将会尽快移除被控侵权内容。

最近更新

社区交流

考试问答