int select(

        int nfds,            //忽略
        fd_ser* readfds,    //指向一个套接字集合,用来检测其可读性
        fd_set* writefds,   // 指向一个套接字结合,用来检测其可写性
        fd_ser* exceptfds, //指向一个套接字集合,用来检测错误
        const struct timeval * timeout   //指定此函数等待的最长时间,如果为NULL,则最长时间为无限大。
);
 
参数说明:
(1)   nfds  windows下未使用,linux下会使用此参数
(2)   readfds:   readfds集合中的套接字发送在以下三种情况中任意一种就会被视为可读,select函数返回后继续留在readfds集合中,不可读的会被移除readfds集合。

1.套接字有数据可读,可以对套接字调用recv函数接收数据
2.套接字的连接已经关闭,重启或者中断,此时应该对套接字进行关闭
3.listen被调用,并且有一个连接未决,对 listen套接字调用accept函数建立新的链接。
(3)   writefds:    readfds集合中的套接字在以下三种情况下会被视为可写
1.使用connect套接字首次建立链接
2.使用accept套接字被接收
3.使用send操作失败,返回WSAEWOULDBLOCK错误,而且缓冲区的空间变得可用
send出去的数据其实都先存在winsock的发送缓冲区中,然后才发送出去,如果缓冲区满了,那么再调用send(WSASend,sendto,WSASendTo)的话,就会返回一个 WSAEWOULDBLOCK的错误码,接下来随着发送缓冲区中的数据被发送出去,缓冲区中出现可用空间时,一个 FD_WRITE 事件才会被触发,这里比较容易混淆的是 FD_WRITE 触发的前提是 缓冲区要先被充满然后随着数据的发送又出现可用空间,而不是缓冲区中有可用空间
(4)   exceptfds   (未使用过,没有进行深入的研究)
1.如果一个非阻塞连接调用正在被处理,连接视图失败
2.OOB数据可读
(5)   timeout:   设置时间,如果超过设定时间,还没有网络事件发生,则返回0,如果此参数为NULL,select会无限等待,直到有一个描述字满足条件。
timeout指向一个timeval结构
typedef struct timeval
{
    long tv_sec;       //只是等待多少秒
    long tv_usec;     //指示等待多少毫秒
} timeval;
如果timeval为{0,0},则select()立即返回,这可用于探询所
选套接口的状态。如果处于这种状态,则select()调用可认为是非阻塞的,且一切适用于非阻塞调用的假设都适用于它
 
具体编程流程
1.初始化套接字集合fdSocket,向这个集合添加监听套接字
2.将fdSocket集合拷贝到fdRead传递给select函数,当有时间发送时,select函数移除fdRead集合中没有未决io操作的套接字
3.比较原来fdSocket集合与select处理后的fdRead集合。确定哪些套接字有未决IO
4.回到第2步继续处理
	my_socket();
my_bind(port);
my_listen(); //PostMessage(h_hand,WM_USER_THREADEND,0,0); //select模型处理过程
//(1).初始化套接字集合fdSocket.添加监听套接字句柄到这个集合
FD_ZERO(&fdSocket);
FD_SET(sSock,&fdSocket); while (1)
{ //(2.)将fdSocket集合的一个拷贝fdRead传递给select函数
//当有时间发生时,select函数一处fdRead集合中没有未决IO操作的套接字句柄,然后返回。
fd_set fdRead = fdSocket;
int nRet = select(0,&fdRead,NULL,NULL,NULL); //timeout参数控制select()完成的时间。若timeout参数为空指针,则select()将一直阻塞
//到有一个描述字满足条件。否则的话,timeout指向一个timeval结构,其中指定了select()
//调用在返回前等待多长时间
//fdwrite 1. 接成功的套接字 在第一次建立连接时,C/S端都会触发一个FD_WRITE事件
//2, 触发的前提是 缓冲区要先被充满然后随着数据的发送又出现可用空间 if(nRet>0)
{
//(3)通过原来的fdSocket集合与select处理后的fdRead集合比较
//确定哪些套接字有未决io,并进一步处理这些io
for(int i=0;i<(int)fdSocket.fd_count;i++)
{
if(FD_ISSET(fdSocket.fd_array[i],&fdRead))
{
if(fdSocket.fd_array[i] == sSock) //(1)监听套接字收到新连接,有新的链接
{
if(fdSocket.fd_count<FD_SETSIZE) //判断集合满了吗?
{ int socke_len = sizeof(remoteAddr); //4.accept
SOCKET cSock = accept(sSock,(SOCKADDR*)&remoteAddr,&socke_len); if(cSock == INVALID_SOCKET)
{
AfxMessageBox("accept failed!\n");
printf("accept failed!\n");
continue;
}
FD_SET(cSock,&fdSocket); //printf("接收到一个连接请求!:%s\r\n",inet_ntoa(remoteAddr.sin_addr) );
//printf("当前连接到服务器的客户端有 %d 个\n",fdSocket.fd_count+1);
socket_id = cSock*(-1); PostMessage(h_hand,WM_USER_THREADEND,0,0); }
else
{
AfxMessageBox("too much connections !\n");
printf("too much connections \n");
continue;
} }
else
{ int nRecv = recv(fdSocket.fd_array[i],readText,sizeof(readText),0);
socket_id = fdSocket.fd_array[i];
if(nRecv>0) //(2)可读
{
readText[nRecv] = '\0'; //HWND g_WindowHandle=((CDialog *)AfxGetMainWnd())->GetSafeHwnd(); PostMessage(h_hand,WM_USER_THREADEND,0,0);
}
else //(3)连接关闭,重启或中断
{
closesocket(fdSocket.fd_array[i]);
FD_CLR(fdSocket.fd_array[i],&fdSocket);
someone_out = TRUE;
PostMessage(h_hand,WM_USER_THREADEND,0,0);
}
}
} } }
else
{
AfxMessageBox("failed select()]n");
printf("failed select()]n");
break; } }

以上只是我在项目中使用的部分代码,最开始的my_socket,my_bind,my_listen都是自己对socket,bind,listen自己重新做的封装

windows socket编程select模型使用的更多相关文章

  1. Windows socket I/O模型 之 select(2)

    在Windows socket I/O模型 之  select(1)中.我们仅仅是在console中简单的模拟了select的处理方法. 还有非常多特性不能改动.比方仅仅能写,不能读. 没使用线程.也 ...

  2. winsock编程select模型

    winsock编程select模型 网络服务端连接数量过多时,为每一个连接申请一个线程会让机器性能急剧下降(大多说是因为线程在用户态和内核态之间切换会占用大量的CPU时间片).为了解决多线程带来的性能 ...

  3. linux tcp/ip编程和windows tcp/ip编程差别以及windows socket编程详解

    最近要涉及对接现有应用visual c++开发的tcp客户端,花时间了解了下windows下tcp开发和linux的差别,从开发的角度而言,最大的差别是头文件(早期为了推广尽可能兼容,后面越来越扩展, ...

  4. Windows Socket 编程_单个服务器对多个客户端简单通讯

    单个服务器对多个客户端程序: 一.简要说明 二.查看效果 三.编写思路 四.程序源代码 五.存在问题 一.简要说明: 程序名为:TcpSocketOneServerToMulClient 程序功能:实 ...

  5. socket之 select模型

    前段时间一直想学习网络编程的select模型,看了<windows网络编程>的介绍,参考了别人的博客. 这里的资料主要来自http://www.cnblogs.com/RascallySn ...

  6. Windows Socket I/O模型

    老陈有一个在外地工作的女儿,不能经常回来,老陈和她通过信件联系.他们的信会被邮递员投递到他们的信箱里.这和Socket模型非常类似.下面我就以老陈接收信件为例讲解Socket I/O模型~~~ 一:s ...

  7. Windows Socket编程精华《TCP通信服务器》

    1.网络中进程之间如何通信? 首要解决的问题是如何唯一标识一个进程,否则通信无从谈起!在本地可以通过进程PID来唯一标识一个进程,但是在网络中这是行不通的.其实TCP/IP协议族已经帮我们解决了这个问 ...

  8. UNIX网络编程-Select模型学习

    1.相关接口介绍 1.1 select ---------------------------------------------------------------------- #include ...

  9. WINDOWS SOCKET编程中accept出来的新连接是阻塞还是非阻塞

    实践证明 SOCKET hNewSock=accept(hListenSock) 当hListenSock为阻塞模型时,hNewSock则为阻塞模型 否则 当hListenSock为非阻塞模型时,hN ...

随机推荐

  1. 让我们一起用开源数据库和开源框架废弃Access

    一.为什么要废弃Access? 1.客户的机子上需要安装access的驱动 ps:这个比较烦人,大家都知道部署越简单越好,安装这个对用户来说太繁琐了. 2.操作时性能不佳 using System; ...

  2. 关于JavaScript变量提升的理解

    废话不说,直接上代码(这是在JavaScript面对对象编程指南上面看到的一个例子) var a=123; function f(){ alert(a); var a=1; alert(a); } f ...

  3. iOS学习笔记——使用ChildViewController

    之前在使用TableView的时候遇到过问题,需要使用另外的TableViewController来先存放TableView,原有的View则使用ViewContainer来引用TableViewCo ...

  4. 纯css3手机页面图标样式代码

    全部图标:http://hovertree.com/texiao/css/19/ 先看效果: 或者点这里:http://hovertree.com/texiao/css/19/hoverkico.ht ...

  5. EF架构~EF异步改造之路~仓储接口的改造

    回到目录 返回异步与并行目录 C#5.0带来了并行编程 {C#1.0托管代码→C#2.0泛型→C#3.0LINQ→C#4.0动态语言→C#5.0异步编程} 随着C#5.0在.net4.5出来之后,它们 ...

  6. 创建javaScript对象的方法

    一.工厂模式 function person (name,age) { var p=new Object(); p.name=name; p.age=age; p.showMessage=functi ...

  7. 解决EP拒绝访问注册表Global键的的问题

    问题描述   打开EP站点时出现如下Error: Message: An unhandled error has occurred. To view details about this error, ...

  8. JavaScript利用装饰模拟实现私有状态

    在经典的面向对象编程中,经常需要将对象的某个状态封装或隐藏在对象内,只有通过对象的一幅幅和能访问这些状态,对外只暴露一些重要的状态变量可以直接读写. 我们可以通过将变量(或参数)装饰在一个构造函数内来 ...

  9. PHP如何连接MySQL数据库

    * PHP连接MySQL数据库 * 准备工作 * 在XAMPP软件的安装目录/php/ext目录中 * php_mysql.dll和php_mysqli.dll文件必须存在 * 在XAMPP软件的安装 ...

  10. golang官网可以打开了 go语言

    golang.org之前国内一直打不开,今天看了一下居然可以打开了,除了页面上youtube的视频加载不了.页面自动识别中文. 再也不用为下载go的源码发愁了.http://www.cnblogs.c ...