现在的位置: 首页 > 综合 > 正文

Select 模型的使用 简单聊天室的实现

2013年10月12日 ⁄ 综合 ⁄ 共 6351字 ⁄ 字号 评论关闭

                                  Select 模型的使用,简单聊天室的实现

       select模型是一种非阻塞的I/O 模型,他主要是使用select来同时管理多个套接字,如果没有网络事件发生,它边进入等待状态,以便执行同步IO;它的好处在于一个线程可以同时管理多个连接的套接字,这样避免了线程的膨胀。

 

      要使用selcet模型的步骤:

      1. 创建socket 

      2. socket 通过bind绑定本地地址

      3. socket  监听

 

       到这里,都是跟阻塞模式的一模一样,下面是不同的

 

      4.设置套接字的模式为阻塞

          u_long value=1;
          iRet=ioctlsocket(socket_listen,FIONBIO ,&value);

 

      5. 调用select 函数     int select(
  int nfds
,
  fd_set* readfds
,
  fd_set* writefds
,
  fd_set* exceptfds
,
  const struct timeval* timeout

);

 

          第一个参数是设为0,不管。第二,三,四个参数都是一个套接字的集合,第二个参数是检测套接字的可读性,第三个检测可写性,第四个检查错误。 第五个设置超时时间,如果为NULL,那么永远等待。第二,三,四个参数不能全为NULL,可以允许其中两个为NULL.

 

          失败返回SOCKET_ERROR也就是-1,如果超时返回0

          所以,判断是否成功,只要判断返回值是否>0就OK。

       select 方法返回后,会在相应的套接字集合fd_set中移除没有网络事件发生的套接字 。

       readfds等待的网络事件:

       1.如果是监听套接字,那么说明有一个连接未决,需要调用accept

       2.如果是普通套接字,有数据可读,需要调用recv

       3.如果是普通套接字,连接关闭,重启,或者 中断       

 

       writefds等待的网络事件:

        1.数据能够发送

        2.如果一个非阻塞连接调用正在处理,连接已经成功

 

       exceptfds等待的网络事件:

        1.如果一个非阻塞连接调用正在处理,连接失败

        2.OOB 数据可读

 

        

 

 

      下面是一个通过Selcet模型来写的类似聊天室的小程序:

  

      服务器端代码:

      

  

      为了实现IP:端口号  跟用户名的对应,定义了一个map<SOCKET,string>来表示对应关系。

      同时,为了实现聊天室的效果,也就是一个人发送消息到服务器,服务器应该分发他的这个消息到所有的其他的客户端,所以增加了一个DispatchToAllClients函数

      代码如下:

     

 

 

      下面是客户端的实现:

      客户端通过一个循环来获得用户的输入,如果有输入,并且不是"quit"和"exit",那么就发送消息到服务器。

      同时为了接受服务器转发的其他Clients发送的消息,创建了一个线程,也是用select模型来等待服务器的read网络事件,如果等待到了,就recv,实现了对服务器的消息的接收已经本身消息的发送的同时进行。

     

       客户端代码:

     

 

     发送消息到服务器的函数SendMessageToServer实现

    

    

 

 

      其中最后退出时候的CloseClient函数,就是断开跟服务器的连接

      

 

 

      线程函数的实现:

     

 

  

 

     

 

     

     

抱歉!评论已关闭.