Windows网络编程之(二)Socket通信非阻塞模式Select(TCP和UDP)
阻塞式的Socket很容易理解,但是使用起来非常别扭。Windows提供了选择(Select)I/O模型,进行异步Socket通信.
Select模型
int select(_In_ int nfds,//忽略. 此参数为了与Berkeley sockets兼容._Inout_ fd_set *readfds,//检查可读性fd_set指针._Inout_ fd_set *writefds,//检查可写性fd_set指针._Inout_ fd_set *exceptfds,//检查错误fd_set指针_In_ const struct timeval *timeout//超时
);
本函数用于确定一个或多个套接口的状态。对每一个套接口,调用者可查询它的可读性、可写性及错误状态信息。用fd_set结构来表示一组等待检查的套接口。在调用返回时,这个结构存有满足一定条件的套接口组的子集,并且select()返回满足条件的套接口的数目。
下面是代码:
#include <Winsock2.h>
#include <stdio.h>
#include <process.h>static const int PORT = 7777;
static const int BUFFER_LENGTH = 128 ;static int g_TotalConn = 0 ;
static SOCKET g_ClientSocket[FD_SETSIZE] ;unsigned int __stdcall WorerkThread(void *);
bool InitWSA() ;int main()
{if(!InitWSA()){return -1 ;}SOCKET sockListen = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP) ;SOCKADDR_IN addrSrv ;addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_LOOPBACK) ;addrSrv.sin_family = AF_INET ;addrSrv.sin_port = htons(PORT) ;bind (sockListen, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR)) ;listen (sockListen, 3) ;_beginthreadex(NULL, 0, WorerkThread, NULL, 0, NULL) ;SOCKADDR_IN addrClient ;int len = sizeof (addrClient) ;while (true){SOCKET client = accept(sockListen, (SOCKADDR *)&addrClient, &len) ;g_ClientSocket[g_TotalConn++] = client ;}closesocket(sockListen) ;WSACleanup () ;return 0 ;
}unsigned int __stdcall WorerkThread(void *)
{printf("线程begin:\n") ;int i;fd_set fdread;fd_set fdwrite;int ret;struct timeval tv = {1, 0};char szMessage[BUFFER_LENGTH];while (true){FD_ZERO(&fdread);FD_ZERO(&fdwrite);for (i = 0; i < g_TotalConn; i++){FD_SET(g_ClientSocket[i], &fdread) ;FD_SET(g_ClientSocket[i], &fdwrite) ;}ret = select(0, &fdread, &fdwrite, NULL, &tv);/*if(g_TotalConn > 0 && ret == SOCKET_ERROR){printf("Socket:an error occurred!\n") ;}*/if (ret == 0){printf("超时\n") ;continue ;}for (i = 0; i < g_TotalConn; i++){if (FD_ISSET(g_ClientSocket[i], &fdread)){ret = recv(g_ClientSocket[i], szMessage, BUFFER_LENGTH, 0);if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET)){printf("Client socket %d closed.\n", i);closesocket(g_ClientSocket[i]);g_ClientSocket[i] = 0 ;if(i != g_TotalConn -1){g_ClientSocket[i--] = g_ClientSocket[g_TotalConn -1] ;}g_TotalConn-- ;}else{szMessage[ret] = '\0';send(g_ClientSocket[i], szMessage, strlen(szMessage), 0);printf("发送数据给Client:%s\n", szMessage) ; }}if (FD_ISSET(g_ClientSocket[i], &fdwrite)){//可以发送数据}}}printf("线程end:\n") ;return 0 ;
}bool InitWSA()
{WORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested = MAKEWORD( 2, 2 );err = WSAStartup( wVersionRequested, &wsaData );if ( err != 0 ) { return false ;}if ( LOBYTE( wsaData.wVersion ) != 2 ||HIBYTE( wsaData.wVersion ) != 2 ) {WSACleanup();return false ; }return true ;
}
特点:
1、程序可能阻塞在select处一段指定的时间。
2、使用轮循的方式,检测Socket是否可读或可写、效率低下。
点评:虽然实现了异步IO,但是实现方式“扭曲”,效率低下,不推荐使用,尤其是服务端。
Windows网络编程之(二)Socket通信非阻塞模式Select(TCP和UDP)相关推荐
- 非阻塞式编程 php,简单介绍PHP非阻塞模式
非阻塞模式是指利用socket事件的消息机制,Server端与Client端之间的通信处于异步状态. 让PHP不再阻塞当PHP作为后端处理需要完成一些长时间处理,为了快速响应页面请求,不作结果返回判断 ...
- Linux 下socket通信终极指南(附TCP、UDP完整代码)
linux下用socket通信,有TCP.UDP两种协议,网上的很多教程把两个混在了一起,或者只讲其中一种.现在我把自己这两天研究的成果汇总下来,写了一个完整的,适合初学者参考,也方便自己以后查阅. ...
- js监听select值变化_网络编程——C++实现socket通信(TCP)高并发之select模式
相关函数: 服务端: socket() bind() listen() FD_ZERO()等辅助函数 select() 高并发select模式 accept() read() 或 recv()等 wr ...
- 网络编程(基于socket接口技术的进程间通信)接上一篇文章补充
目录 一.网络编程(基于socket接口技术) 1.基于TCP协议的网络通信 编程模型: 2.基于UDP通信协议的网络通信 编程模型: 3.新增函数: 大小端数据转换函数: ip地址转换函数: TCP ...
- UE4 Socket多线程非阻塞通信【2】
昨日不可追, 今日尤可为.勤奋,炽诚,不忘初心 紧接着第一部分,别说话,勿打断我游离的思绪我们走我们走... 二.消息结构&收发队列 先不急着往下走,先捋一捋,不知道自己要干什么地走下去是一件 ...
- UE4 Socket多线程非阻塞通信【1】
昨日不可追, 今日尤可为.勤奋,炽诚,不忘初心 前面写了一篇有关于虚幻4加载第三方库的博客思前顾后,感觉细节还是有必要拎起来注意下. ue4自带的Fsocket用起来依旧不是那么的顺手,感觉超出了我的 ...
- socket的阻塞模式和非阻塞模式(send和recv函数在阻塞和非阻塞模式下的表现)
socket的阻塞模式和非阻塞模式 无论是Windows还是Linux,默认创建socket都是阻塞模式的 在Linux中,可以再创建socket是直接将它设置为非阻塞模式 int socket (i ...
- java socket 阻塞模式_(四) 如何将socket设置为非阻塞模式
1. windows平台上无论利用socket()函数还是WSASocket()函数创建的socket都是阻塞模式的: SOCKET WSAAPI socket( _In_ int af, ...
- socket阻塞和非阻塞模式
socket阻塞和非阻塞模式 本文讨论Linux下的socket套接字 一.同步.异步阻塞和非阻塞 同步:主动请求并等待IO操作完成的方式 异步:主动请求数据后,可以去处理其它任务,随后等待IO操作完 ...
- 《Windows网络编程案例教程》-董相志 学习记录 阻塞/非阻塞套接字编程
<Windows网络编程案例教程>-董相志 学习记录 阻塞/非阻塞套接字编程 2.3 阻塞/非阻塞套接字编程 阻塞套接字编程通信流程图 2.3.1 阻塞套接字客户机编程 1.启动并初始化W ...
最新文章
- Oracle Exadata 简介
- R语言广义线性模型函数GLM、(Model fit and regression diagnostics)、模型充分性评估方法、使用plot函数以及car包函数
- LeetCode 215. Kth Largest Element in an Array--数字第K大的元素--最大堆或优先队列--C++,Python解法
- Tapestry IoC Decorator
- python 数据分析学什么-如何在业余时学数据分析?
- jvm在不同系统中的最大内存空间地址
- oracle 数据库的数据事务的相关概念
- 4加密问题漏洞修复_Apache Shiro 反序列化漏洞实战
- 《C++ Primer Plus》16.2 智能指针模板类
- Java-GuardedBlocks与BusyWaitting忙等待
- java jackson_Jackson 框架的高阶应用
- 封装判断一个字符的后缀名和前缀的方法
- JS中clientHeight、scrollHeight、offsetHeight、scrollTop、offsetTop的定义
- 新基建促进智能化基础设施管控平台的搭建
- 大数据scala面试题汇总
- 绩效/加薪/年终奖,虐你如初恋
- Python------2022-1-11作业
- Word表格外的第一个空行如何删除
- 【沐风老师】3dMax Gyroid Minimal Surface 极小曲面建模详细教程
- error writing messa ge: File too large