Windows C++ TCP开发(使用select函数以及设置非阻塞/Reuse属性)
1、select官方函数说明:
语法
C++
int WSAAPI select([in] int nfds,[in, out] fd_set *readfds,[in, out] fd_set *writefds,[in, out] fd_set *exceptfds,[in] const timeval *timeout );参数
[in] nfds已忽略。 包含 nfds 参数只是为了与 Berkeley 套接字兼容。
[in, out] readfds一个可选指针,指向要检查的一组套接字的可读性。
[in, out] writefds指向要检查可写性的一组套接字的可选指针。
[in, out] exceptfds指向要检查错误的一组套接字的可选指针。
[in] timeout选择等待的最长时间,以 TIMEVAL 结构的形式提供。 将阻止操作的 超时 参数设置为 null 。
返回值
select 函数返回fd_set结构中已就绪并包含的套接字句柄总数;如果时间限制过期,则返回 0;如果发生错误,则返回SOCKET_ERROR。 如果返回值SOCKET_ERROR,则 WSAGetLastError 可用于检索特定的错误代码。
2、阻塞设置
unsigned long cmd = 1;
nRet = ioctlsocket(sclient, FIONBIO, &cmd);
if (SOCKET_ERROR == nRet)
{
printf("Failed to set FIONBIOsocket!\n");
WSACleanup();
return 0;
}
3、设置端口 Reuse属性
bool bReuseAddr = true;
//设置端口SO_REUSEADDR属性,端口释放后可以立即被使用。
nRet = setsockopt(sclient, SOL_SOCKET, SO_REUSEADDR, (char *)&bReuseAddr, sizeof(bReuseAddr));
if (SOCKET_ERROR == nRet)
{
printf("Failed to set resueaddr socket!\n");
WSACleanup();
return 0;
}
什么是resuse属性:端口复用最常用的用途应该是防止服务器重启时之前绑定的端口还未释放或者程序突然退出而系统没有释放端口。这种情况下如果设定了端口复用,则新启动的服务器进程可以直接绑定端口。如果没有设定端口复用,绑定会失败,提示ADDR已经在使用中,必须等超时时间大概是2分钟。
4、TCP代码+select
4.1 TCP 服务端代码
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <WINSOCK2.H>#pragma comment(lib,"ws2_32.lib")
#define INT_SERVER_PORT 8888
#define STR_SERVER_IP "127.0.0.1"
#define INT_DATABUFFER_SIZE 100void main(void)
{
//与WSACleanup函数配对使用
WORD dwVersion = MAKEWORD(2, 2);
WSAData wsaData;
WSAStartup(WINSOCK_VERSION, &wsaData);//创建套接字
SOCKET sockServer = socket(AF_INET, SOCK_STREAM, 0);
if (INVALID_SOCKET == sockServer)
{
printf("Failed to create socket!\n");
WSACleanup();
return;
}//本地地址初始化
sockaddr_in addrServer;
memset(&addrServer, 0, sizeof(sockaddr_in));
addrServer.sin_family = AF_INET;
addrServer.sin_port = htons(INT_SERVER_PORT);
addrServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY);int nRet = 0;
bool bReuseAddr = true;
//设置端口SO_REUSEADDR属性,端口释放后可以立即被使用。
nRet = setsockopt(sockServer, SOL_SOCKET, SO_REUSEADDR, (char *)&bReuseAddr, sizeof(bReuseAddr));
if (SOCKET_ERROR == nRet)
{
printf("Failed to set resueaddr socket!\n");
WSACleanup();
return;
}//设置端口非阻塞
unsigned long cmd = 1;
nRet = ioctlsocket(sockServer,FIONBIO,&cmd);
if (SOCKET_ERROR == nRet)
{
printf("Failed to set resueaddr socket!\n");
WSACleanup();
return;
}nRet = bind(sockServer, (sockaddr *)&addrServer, sizeof(addrServer));
if (SOCKET_ERROR == nRet)
{
printf("Failed to bind address!\n");
WSACleanup();
return;
}if (0 != listen(sockServer, 5))
{
printf("Failed to listen client!\n");
WSACleanup();
return;
}UINT i = 0;
fd_set fd;
FD_ZERO(&fd);
FD_SET(sockServer, &fd);/*
timeval tm;
tm.tv_sec = 0;
tm.tv_usec = 1000;
*/
while (1)
{
fd_set fdOld = fd;
nRet = select(0, &fdOld, NULL, NULL,/*&tm*/NULL);
if (0 <= nRet)
{
for (i = 0; i < fd.fd_count; i++)
{
if (FD_ISSET(fd.fd_array[i], &fdOld))
{
if (fd.fd_array[i] == sockServer)//接收到新的连接
{
SOCKET sockAccept;
sockaddr_in addrAccept;
int iAcceptLen = sizeof(addrAccept);
memset(&addrAccept, 0, sizeof(addrAccept));
sockAccept = accept(sockServer, (sockaddr *)&addrAccept, &iAcceptLen);
if (INVALID_SOCKET != sockAccept)
{
send(sockAccept, "Hello Client", strlen("Hello Client"), 0);
FD_SET(sockAccept, &fd);
printf("%s:%d has connected server!\n", inet_ntoa(addrAccept.sin_addr),
ntohs(addrAccept.sin_port));
}
}
else //非服务器,接收数据(因为fd是读数据集)
{
char szDataBuff[INT_DATABUFFER_SIZE];
int iRecvSize;
memset(szDataBuff, 0, INT_DATABUFFER_SIZE);
iRecvSize = recv(fd.fd_array[i], szDataBuff, INT_DATABUFFER_SIZE, 0);
if (SOCKET_ERROR == iRecvSize)
{
closesocket(fd.fd_array[i]);
FD_CLR(fd.fd_array[i], &fd);
i--;
printf("Failed to recv data ,or Client has disconnected, errorcode:%d.\n", WSAGetLastError());
continue;
}if (0 == iRecvSize)
{
//客户socket关闭
closesocket(fd.fd_array[i]);
FD_CLR(fd.fd_array[i], &fd);
i--;
}if (0 < iRecvSize)
{
//打印接收的数据
printf("recv data:%s\n",szDataBuff);
}
}
}
}
}
else if (SOCKET_ERROR == nRet)
{
printf("Faild to select sockt in server! Error Code[%d]\n", WSAGetLastError());
Sleep(100);
}
}
WSACleanup();
}
4.2 TCP客户端代码
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <WINSOCK2.H>
using namespace std;
#pragma comment(lib, "ws2_32.lib")int main()
{
//与WSACleanup函数配对使用
WORD sockVersion = MAKEWORD(2, 2);
WSADATA data;
if (WSAStartup(sockVersion, &data) != 0)
{
return 0;
}//创建客户端套接字
SOCKET sclient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sclient == INVALID_SOCKET)
{
printf("invalid socket!");
return 0;
}//初始化SOCKET结构体
sockaddr_in serAddr;
serAddr.sin_family = AF_INET;
serAddr.sin_port = htons(8888);
serAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
if (connect(sclient, (sockaddr *)&serAddr, sizeof(serAddr)) == SOCKET_ERROR)
{ //连接失败
printf("connect error !");
closesocket(sclient);
return 0;
}int nRet = 0;
bool bReuseAddr = true;
//设置端口SO_REUSEADDR属性,端口释放后可以立即被使用。
nRet = setsockopt(sclient, SOL_SOCKET, SO_REUSEADDR, (char *)&bReuseAddr, sizeof(bReuseAddr));
if (SOCKET_ERROR == nRet)
{
printf("Failed to set resueaddr socket!\n");
WSACleanup();
return 0;
}//设置端口非阻塞
unsigned long cmd = 1;
nRet = ioctlsocket(sclient, FIONBIO, &cmd);
if (SOCKET_ERROR == nRet)
{
printf("Failed to set resueaddr socket!\n");
WSACleanup();
return 0;
}//发送数据
send(sclient, "Hello Server", strlen("Hello Server"), 0);//接收数据
while (true)
{
fd_set fd;
FD_ZERO(&fd);
FD_SET(sclient, &fd);
nRet = select(0, &fd, NULL, NULL,NULL);
if (0 <= nRet)
{
char recData[255];
int ret = recv(sclient, recData, 255, 0);
if (ret > 0) {
recData[ret] = 0x00;
printf("Recv :%s\n",recData);
}
else
{
printf("Socket Error or Socket has closed\n");
break;
}
}
else if (nRet == SOCKET_ERROR)
{
printf("Faild to select sockt in server! Error Code[%d]\n", WSAGetLastError());
break;
}
}
closesocket(sclient);
WSACleanup();
return 0;
}
相关文章:
Windows C++ TCP开发(使用select函数以及设置非阻塞/Reuse属性)
1、select官方函数说明: 语法 C int WSAAPI select([in] int nfds,[in, out] fd_set *readfds,[in, out] fd_set *writefds,[in, out] fd_set *exceptfds,[in] const timeval *timeout );参数 [in] nfds 已忽略。 包含 nf…...
ARM TrustZone技术解析:构建嵌入式系统的安全扩展基石
🌈个人主页: Aileen_0v0 🔥热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法|MySQL| 💫个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-LOdvohfCEnd8eKyd {font-family:"trebuchet ms",verdana,arial,sans-serif;f…...
初识Python语言-课堂练习【pyhton123题库】
初识Python语言-课堂练习【pyhton123题库】 一、单项选择题 1、Guido van Rossum正式对外发布Python版本的年份是: A 2008B 1998C 1991D 2002 【答案】C 【解析】暂无解析2、下面不是Python语言特点的是:…...
chrome高内存占用问题
chrome号称内存杀手不是盖的,不设设置的话,经常被它内存耗尽死机是常事。以下自用方法 1 自带的memory saver chrome://settings/performance PerformanceMemory Saver When on, Chromium frees up memory from inactive tabs. This gives active tab…...
【C语言】文件操作篇-----程序文件和数据文件,文件的打开和关闭,二进制文件和文本文件,fopen,fclose【图文详解】
欢迎来CILMY23的博客喔,本篇为【C语言】文件操作篇-----程序文件和数据文件,文件的打开和关闭,二进制文件和文本文件【图文详解】,感谢观看,支持的可以给个一键三连,点赞关注收藏。 前言 在了解完动态内存管…...
知识碎片收集
目录 1. 如何计算两点经纬度之间的距离2. 加权随机采样3.什么时LLDB和GDB 1. 如何计算两点经纬度之间的距离 1.知乎-如何计算两点经纬度间距离 2.根据两点经纬度坐标计算距离 3.根据经纬度计算两点之间的距离的公式推导过程以及google.maps的测距函数 4.根据经纬度点计算经…...
不可不知!用例图的绘制与应用全指南深度解析
在软件开发领域中,用例图是一种强大的工具,用于描述系统的功能需求以及系统与外部实体之间的交互。无论是在需求分析阶段还是在系统设计过程中,用例图都扮演着至关重要的角色。本文将全面介绍用例图的绘制方法和其在软件开发中的应用…...
【数据结构七】堆与PriorityQueue详解
堆 在Java中有一种数据结构基于队列,并保证操作的数据带有优先级,该数据结构应该提供了两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象。这种数据结构就是优先级队列(Priority Queue)。它的底层使用了堆这种数据结…...
uniapp写支付的操作
支付的时候一般需要几个参数: ‘timeStamp’: 时间戳,‘nonceStr’: 随机字符串,不超过32位‘package’: 下单后接口返回的prepauid‘signType’: 签名的算法‘paySign’: 后端会给前端一个签名sign: data.sign // 根据签名算法生成签名 <template&…...
微信小程序开发系列(二十四)·wxml语法·列表渲染·wx:for-item 和 wx:for-index
目录 1. 如果需要对默认的变量名和下标进行修改,可以使用wx:for-item 和 wx:for-index 2. 将 wx:for 用在 标签上,以渲染一个包含多个节点的结构块 方法一 方法二 3. 总结 3.1 wx:for-item 和 wx:for-index总结 3.2 总结 1. 如果需要对默…...
下载无水印抖音视频
在抖音看到某些视频想下载,却出现无法保存在本地【显示"作品暂时无法保存,链接已复制"】。或者下载的视频有水印。 而某些微信小程序下载可能需要付费或者有水印。其实我们可以直接使用电脑浏览器直接下载。 举个例子: 这是来自王道官方账号的一条视频链…...
L1-039 古风排版(C++)
中国的古人写文字,是从右向左竖向排版的。本题就请你编写程序,把一段文字按古风排版。 输入格式: 输入在第一行给出一个正整数N(<100),是每一列的字符数。第二行给出一个长度不超过1000的非空字符串&a…...
springboot项目docker分层构建
一、需求场景 在使用dockerfile构建springboot项目时,速度较慢,用时比较长,为了加快构建docker镜像的速度,采用分层构建的方式 二、构建配置 1、pom.xml配置 <properties><project.build.sourceEncoding>UTF-8<…...
深入理解SPA、CSR与SSR的区别及应用
随着Web技术的快速发展,前端开发架构也在不断演进。在现代Web应用中,单页面应用(SPA)、客户端渲染(CSR)和服务器端渲染(SSR)是三种常见的实现方式,它们各自拥有独特的特性…...
基于电鳗觅食优化算法(Electric eel foraging optimization,EEFO)的无人机三维路径规划(提供MATLAB代码)
一、无人机路径规划模型介绍 无人机三维路径规划是指在三维空间中为无人机规划一条合理的飞行路径,使其能够安全、高效地完成任务。路径规划是无人机自主飞行的关键技术之一,它可以通过算法和模型来确定无人机的航迹,以避开障碍物、优化飞行…...
将SQL数据库转换为Mysql数据库
一、准备工作 1、SQL server安装包与已经有数据的mdf、ldf数据库文件; 2、.net Framework安装包;(用于支持SQL Server安装的组件) 3、MySql安装包;(用于目标数据库的环境安装) 4、navicat安装包…...
Java集合进阶
双列集合 单列集合的特点:一次添加一个。 双列集合的特点:一次添加一对/键值对/键值对对象/Entry。 左键(不可重复)右值(可重复),一一对应。 Map是双列集合的顶层接口,他的功能是…...
一.算法基础
目录 1.算法基础 2.算法概念 3.时间复杂度--用来评估算法运行效率的一个式子 如何简单快速的判断算法复杂度? 4.空间复杂度 1.算法基础 2.算法概念 --静态动态 3.时间复杂度--用来评估算法运行效率的一个式子 ----一个单位!!! 1-在什么配置下运行(机器) 2-问题的规模…...
python自学7
第二章第一节面向对象 程序的格式都不一样,每个人填写的方式也有自己的习惯,比如收集个人信息,可能有人用字典字符串或者列表, 类的成员方法 类和对象 构造方法 挨个传输值太麻烦了,也没有方便点的,有&…...
Umi - 刷新后页面报404
Umi 项目本地运行刷新没问题,但是部署之后刷新页面报404。因为Umi 默认是用 browser 模式,需要做一下处理。 以下是官方给出解决方案。 一、解决方案 1. 方案一:改用hashHistory .umirc.js {history: { type: hash }, }这个方案项目打包…...
用labview制作的上位机界面的多语言显示
在工控系统中,特别是有国外项目的时候,多语言显示必不可少。labview的控件的显示项里,有一个“标题”项,用标题就可以实现多语言显示,因为在labview中,标签是唯一的,而标题是可以重复的。首先&a…...
鸿蒙问卷投票台页面构建:问卷统计与状态网格模块详解
鸿蒙问卷投票台页面构建:问卷统计与状态网格模块详解 前言 在 HarmonyOS 6.0 应用开发中,问卷调研类页面的核心挑战在于如何清晰展示问卷进度、回收数据和题型分布。本文将以“问卷投票台”应用的主页面为例,深入解析如何在鸿蒙平台上构建问卷…...
专业级AI音频处理实战指南:OpenVINO插件让Audacity变身智能音频工作站 [特殊字符]
专业级AI音频处理实战指南:OpenVINO插件让Audacity变身智能音频工作站 🎵 【免费下载链接】openvino-plugins-ai-audacity A set of AI-enabled effects, generators, and analyzers for Audacity. 项目地址: https://gitcode.com/gh_mirrors/op/openv…...
2026最新免费在线去水印工具详细教程,在线去本地视频水印保姆级指南
你是不是也遇到过这种情况?辛辛苦苦在网上找到一个绝美视频素材想用在剪辑里,结果画面正中央横着一个硕大的水印;或者刷小红书看到一段干货满满的教学视频,想保存下来反复学习,却被角落的Logo劝退。更头疼的是…...
丈母娘只要第一眼看不上女婿,即使后面结婚了,大概率也会一直看不上,大家觉得对吗?——为什么有些丈母娘总是挑女婿的不是,没事就发货大吼?——
很多家庭里,确实存在这种现象,但“第一眼看不上=一辈子看不上”,并不是绝对规律。 丈母娘对女婿的第一印象往往很强,因为她看的不是单纯“喜不喜欢”,而是: 这个男人靠不靠谱 能不能让女儿过得稳定 性格是否成熟 家庭背景、经济能力、处事方式是否安心 对女儿有没有…...
【Sora 2视频后期处理黄金法则】:20年AI影像专家亲授5大不可绕过的帧级调优技巧
更多请点击: https://codechina.net 第一章:Sora 2视频后期处理的底层逻辑与帧级思维重构 Sora 2并非传统时间轴驱动的剪辑工具,其视频后期处理建立在扩散模型与隐空间帧序列联合优化的基础之上。每一帧不再作为孤立图像存在,而是…...
Kubernetes多集群管理策略:统一管理多个K8s集群
Kubernetes多集群管理策略:统一管理多个K8s集群 一、多集群管理概述 Kubernetes多集群管理是指在企业环境中管理多个独立的Kubernetes集群,实现统一的部署、监控和运维。 1.1 多集群场景 场景说明示例地域隔离不同区域部署独立集群北京、上海、广州各…...
2026年一键生成论文工具实测精选:5款神器从构思到提交全流程护航
写论文的焦虑,是每个科研人和学生都无法回避的日常。选题无从下手,文献检索耗时费力,格式排版反复调整,查重降重更是让人抓耳挠腮。到了2026年,AI工具早已不再只是“敲字机器”,而是进化成了能陪你从构思到…...
每日热门skill:你的AI终于有“脑子“了!Memory MCP Server让Claude记住你的一切
告别"金鱼记忆",打造真正懂你的AI助手 一、开篇:那个让你崩溃的瞬间 你有没有遇到过这种情况? 昨天刚跟Claude说过:“我是做后端开发的,对Python比较熟悉,前端不太行。” 今天再问:“帮我写个React组件。” 它热情洋溢地回复:“好的!这是一个完整的全栈…...
在Python项目中实现故障转移通过Taotoken自动切换备用大模型
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 在Python项目中实现故障转移通过Taotoken自动切换备用大模型 应用场景类,面向构建高可用AI应用的中高级开发者。当核心…...
