socket编程总结(2)[1]

[入库:2005年8月19日] [更新:2007年3月24日]

本文简介:选择自 hxzb7215191 的 blog

当然tcp方式的模型还有事件选择模型。
就是把所有的网络事件和我们的一个程序里定义的事件梆定。
这个有它的好处,可能可以让我们更好的写一个线程来管理
接收与发送。
现在来讲一下一个完成端口模型。

  完成端口
 
 一个完成端口其实就是一个通知队列,由操作系统把已经完成的重叠i/o请求的通知
 放入其中。当某项i/o操作一旦完成,某个可以对该操作结果进行处理的工作者线程
 就会收到一则通知。而套接字在被创建后,可以在任何时候与某个完成端口进行关
 联。
 
 步骤:
 1、创建一个空的完成端口;
 2、得到本地机器的cpu个数;
 3、开启cpu*2个工作线程(又名线程池),全部都在等待完成端口的完成包;
 4、创建tcp的监听socket,使用事件邦定,创建监听线程;
 5、当有人连接进入的时候,将client socket保存到一个我们自己定义的关键键,
    并把它与我们创建的完成端口关联;
 6、使用wsarecv和wsasend函数投递一些请求,这是使用重叠i/o的方式;
 7、重复5~6;

 注:1、重叠i/o的方式中,接收与发送数据包的时候,一定要进行投递请求这是
   它们这个体系结构的特点
   当然,在完成端口方式中,不是直接使用的wsarecv和wsasend函数进行请求
   的投递的。而是使用的readfile,write的方式
  2、完成端口使用了系统内部的一些模型,所以我们只要按照一定的顺序调用就
   可以完成了。
  3、完成端口是使用在这样的情况下,有成千上万的用户连接的时候,它能够
   保证性能不会降低。


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

#define port 5150
#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;

   if ((ret = wsastartup(0x0202, &wsadata)) != 0)
   {
      printf("wsastartup failed with error %d\n", ret);
      return;
   }

   //打开一个空的完成端口

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

   // 开启cpu个数的2倍个的线程

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

   //打开一个服务器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;
   }

   //开始接收从客户端来的连接

本文关键:socket编程总结(2)
  相关方案
Google
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top