C语言辅导:面向短连接的网络服务器计算机二级考试

文章作者 100test 发表时间 2009:04:30 07:45:31
来源 100Test.Com百考试题网


  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年上半年全国计算机等级考试试题答案汇总



相关文章


C语言辅导:用C语言实现禁用网卡的代码计算机二级考试
二级考试C语言辅导:C语言计算奖金发放实例计算机二级考试
二级考试C语言辅导:远程运行程序的一种方法计算机二级考试
C语言辅导:面向短连接的网络服务器计算机二级考试
计算机二级考试C语言辅导:log4cxx输出到界面计算机二级考试
计算机二级考试C语言辅导:进程模块查看计算机二级考试
C语言开发实现的虚拟桌面程序代码计算机二级考试
澳大利亚华人论坛
考好网
日本华人论坛
华人移民留学论坛
英国华人论坛