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. 从零开始学 Java - 我放弃了 .NET ?

    这不是一篇引起战争的文章 毫无疑问,我之前是一名在微软温暖怀抱下干了近三年的 .NET 开发者,为什么要牛(sha)X一样去搞 Java 呢?因为我喜欢 iOS 阿!哈哈,开个玩笑.其实,开始学 Ja ...

  2. Dapper ORM VS SqlSugar ORM的 8场对决

    CUP和.NET SQL版本不同也会存在少许差距,但不会有质变,下面的测试结果仅供参考 比赛规则 1.统一使用Realse版本的最新 DLL,Realse模式启用程序 2.为了平衡CPU和数据库空闲情 ...

  3. NSPredicate 的使用

    NSPredicate是什么? NSPredicate 是预测的意思 但是我们常翻译成谓词 它可以干什么? 使用NSPredicate可以定义模糊查询条件 根据一定的条件 我们就可以从一个数组中快速找 ...

  4. C# DataGrid根据某列的内容设置行字体加粗 单元格设置对齐方式

    最近做了个功能,DataGrid显示具体内容的时候,根据某列分组. 每个分组具体内容后边,增加一行显示合计信息. 查询数据时,使用了union all将分组数据与明细数据合并起来,使用了排序达到了预期 ...

  5. html5 前端图片处理(预览、压缩、缩放)

    现在手机图片是越来越大了,上传图片流量耗费巨大.同时预览也是一个问题,所以利用HTML5 file和canvas来解决这个问题. var upload = { _o: null,//对象id _aut ...

  6. HTTP文件断点续传的原理

    前几天一个同事跑过来找我说,我们在广告素材视频这块想做断点续传,就是这次某个视频缓存到一半,下次不用重头开始,可以在原来停留得位置开始继续下载.以提供更好的用户体验. 同时说需要我们支持吐素材地址的业 ...

  7. 转载:《TypeScript 中文入门教程》 11、声明合并

    版权 文章转载自:https://github.com/zhongsp 建议您直接跳转到上面的网址查看最新版本. 介绍 TypeScript有一些独特的概念,有的是因为我们需要描述JavaScript ...

  8. java Properties异常:Malformed \uxxxx encoding.

    昨天项目中遇到一个 java.lang.IllegalArgumentException: Malformed \uxxxx encoding.这样的一个异常,debug了一下发现是读取propert ...

  9. 学习.NET是因为热爱 or 兴趣 or 挣钱?

    看到最近园子里掀起了“.NET快不行了”.“.NET工资太低了”.“转行做XX”等一系列之风,不由得想说点什么,我只是基于自己的观点,你认同或者不认同,我就是这样认为,无所谓对与错,写文章就是为了交流 ...

  10. JMeter专题系列(四)参数化

    JMeter也有像LR中的参数化,本篇就来介绍下JMeter的参数化如何去实现. 参数化:录制脚本中有登录操作,需要输入用户名和密码,假如系统不允许相同的用户名和密码同时登录,或者想更好的模拟多个用户 ...