博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WinSockets编程(六)select模式
阅读量:6335 次
发布时间:2019-06-22

本文共 4387 字,大约阅读时间需要 14 分钟。

select模式的思想

创建FD_SET fd_all,并初始化FD_ZERO(&fd_all);

Step1  初始时: 

Step2   加入一个套接字之后,比如FD_SET(sServer,&fd_all);

Step3   调用select函数之后,有两种情况

上述的select假设是在非阻塞的情况下。由图示可以看出, select对FD_SET的结构进行了动态改变,没有变化的会置为0,有变化的会保持为1,这就是select的思想。

//

保持FD_SET的状态

假设有1,2,3,4四个标号的套接字加入FD_SET

//伪码FD_SET(1,&fd_all);FD_SET(2,&fd_all);FD_SET(3,&fd_all);FD_SET(4,&fd_all);for(;;){    ...    select(0,&fd_all,0,NULL,NULL);    ...}

在进行选择之后,有些套接字可能暂时没有数据收发就被select函数过滤掉了,所以要保持套接字的状态,模式如下:

//保持套接字状态的方法示例    while(true)    {        fd_read=fd_all;        fd_write=fd_all;        select(0,&fd_read,0,NULL,NULL);//①阻塞;        for(UINT i=0;i

 

版本一(有点问题,需要修正):

/**************************************************************************************************************

2018/10/9号进行修正:

原因:

1. 在select轮询时,如果没有连接返回-1

2. 在while循环时,需要Sleep(100),不然CPU空转太厉害导致CPU使用率上升!

/**************************************************************************************************************

#include 
#include
#include
#pragma comment(lib,"ws2_32.lib")#define PORT 8000#define MSGSIZE 255#define SRV_IP "127.0.0.1"int g_nSockConn = 0; //请求连接的数目struct ClientInfo{ SOCKET sockClient; //客户端套接字 SOCKADDR_IN addrClient; //客户端地址};ClientInfo g_Client[FD_SETSIZE]; //客户端套接字集合;DWORD WINAPI WorkThread(LPVOID lpParameter);int main(int argc, char *argv[]){ WSADATA wsd; WSAStartup(MAKEWORD(2, 2), &wsd); SOCKET sockListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//创建套接字 SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = inet_addr(SRV_IP); addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(PORT); bind(sockListen, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));//绑定 listen(sockListen, 64);//监听 DWORD dwThreadIDRecv = 0; DWORD dwThreadIDWrite = 0; HANDLE hand = CreateThread(NULL, 0, WorkThread, NULL, 0, &dwThreadIDRecv);//工作线程 if (hand == NULL) { std::cout <<"创建线程失败!"<

 版本二(正常运行):

#include 
#include "initSocket.h"CInitSock theSock; int main(){ USHORT nPort = 4567; SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(nPort); sin.sin_addr.S_un.S_addr = INADDR_ANY; if (::bind(sListen, (sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR) { printf(" Failed bind() \n"); return -1; } ::listen(sListen, 5); fd_set fdSocket; FD_ZERO(&fdSocket); FD_SET(sListen, &fdSocket); while (TRUE) { fd_set fdRead = fdSocket; int nRet = ::select(0, &fdRead, NULL, NULL, NULL); if (nRet > 0) { for (int i = 0; i < (int)fdSocket.fd_count; i++) { if (FD_ISSET(fdSocket.fd_array[i], &fdRead)) { if (fdSocket.fd_array[i] == sListen) { if (fdSocket.fd_count < FD_SETSIZE) { sockaddr_in addrRemote; int nAddrLen = sizeof(addrRemote); SOCKET sNew = ::accept(sListen, (SOCKADDR*)&addrRemote, &nAddrLen); FD_SET(sNew, &fdSocket); printf("接收到连接(%s)\n", ::inet_ntoa(addrRemote.sin_addr)); } else { printf(" Too much connections! \n"); continue; } } else { char szText[256]; int nRecv = ::recv(fdSocket.fd_array[i], szText, strlen(szText), 0); if (nRecv > 0) // (2)可读 { szText[nRecv] = '\0'; printf("接收到数据:%s \n", szText); } else { printf("连接断开...!"); ::closesocket(fdSocket.fd_array[i]); FD_CLR(fdSocket.fd_array[i], &fdSocket); } } } } } else { printf(" Failed select() \n"); break; } } return 0;}

 

转载于:https://www.cnblogs.com/tinaluo/p/7698624.html

你可能感兴趣的文章
HoloLens开发手记 - Vuforia开发概述 Vuforia development overview
查看>>
Android支付之支付宝封装类
查看>>
<亲测>CentOS中yum安装ffmpeg
查看>>
【分享】马化腾:产品设计与用户体验
查看>>
【机器学习PAI实践十】深度学习Caffe框架实现图像分类的模型训练
查看>>
全智慧的网络:思科十年来最具颠覆性的创新
查看>>
怎样将现有应用迁移到 VMware NSX
查看>>
赛门铁克收购以色列移动安全初创公司Skycure 旨在构建网络安全防御平台
查看>>
《Photoshop蒙版与合成(第2版)》目录—导读
查看>>
《团队软件过程(修订版)》—第1章1.3节TSPi的设计
查看>>
“最佳人气奖”出炉!4月27号,谁能拿到阿里聚安全算法挑战赛的桂冠?
查看>>
《网页美工设计Photoshop+Flash+Dreamweaver从入门到精通》——2.6 图层与图层样式...
查看>>
《iOS组件与框架——iOS SDK高级特性剖析》——第2章,第2.7节获取线路
查看>>
Spring中 @Autowired标签与 @Resource标签 的区别
查看>>
人工智能凭什么毁灭人类
查看>>
[LeetCode]--349. Intersection of Two Arrays
查看>>
tomcat启动报错
查看>>
mongorocks引擎原理解析
查看>>
用Swift实现一款天气预报APP(一)
查看>>
oracle11g R2 RAC卸载grid
查看>>