当前位置: 首页 > news >正文

测试Winsock的select

说明

实现了一个回显一行字符串的服务器:客户端发送一行字符串,一’\n’结尾,服务器接受完一行后就原封不动地发回给客户端。
windows下对select的能监控的Socket数量是有限制的,若超过,一种方案是再开一个线程。

#ifndef FD_SETSIZE
#define FD_SETSIZE      64
#endif /* FD_SETSIZE */

代码

#include <iostream>
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <WinSock2.h>
#include <vector>
#include <memory>#pragma comment(lib, "Ws2_32.lib")struct ClientSocketItem
{ClientSocketItem(){hSocket = NULL;memset(szRecv, 0, sizeof(szRecv));nRecvSize = 0;bNeedWrite = false;nWriteOffset = 0;}SOCKET hSocket;char szRecv[1024];unsigned int nRecvSize;std::string strIp;bool bNeedWrite;//接受完成,可以发送unsigned int nWriteOffset = 0;
};std::vector<std::shared_ptr<ClientSocketItem>> g_Clients;void do_accept(SOCKET hListenSocket)
{sockaddr_in mPeerAddr = { 0 };int nAddrLen = sizeof(sockaddr);SOCKET hClientSocket = accept(hListenSocket, (sockaddr*)(&mPeerAddr), &nAddrLen);if (INVALID_SOCKET == hClientSocket){std::cout << "accept failed with error "<< WSAGetLastError() << std::endl;}else{unsigned long nNoBlock = 0;ioctlsocket(hClientSocket, FIONBIO, &nNoBlock);std::string strIpAddr = inet_ntoa(mPeerAddr.sin_addr);std::cout << "accept success, peer ip is " << strIpAddr.c_str() << std::endl;auto pClient = std::make_shared<ClientSocketItem>();pClient->hSocket = hClientSocket;pClient->strIp = strIpAddr;g_Clients.push_back(pClient);}
}bool do_read(const std::shared_ptr<ClientSocketItem>& pClient )
{if (!pClient){return false;}char c = 0; //测试用,每次只读一个字符int nRecvValue = recv(pClient->hSocket, &c, 1, 0);if (nRecvValue > 0){pClient->szRecv[pClient->nRecvSize] = c;pClient->nRecvSize += 1;std::cout << "read one char: " << c << std::endl;if (c == '\n'){std::cout << "read finished" << std::endl;pClient->bNeedWrite = true;}return true;}else if (0 == nRecvValue){std::cout << "peer client closed" << std::endl;closesocket(pClient->hSocket);return false;}else{int nError = WSAGetLastError();if (WSAEWOULDBLOCK != nError){std::cerr << "recv failed with error " << nError << std::endl;closesocket(pClient->hSocket);return false;}std::cout << "next recv" << std::endl;return true;}
}bool do_write(const std::shared_ptr<ClientSocketItem>& pClient)
{if (!pClient){return false;}if (!pClient->bNeedWrite){return true;}//测试用,每次只发送一个字符int nRet = send(pClient->hSocket, pClient->szRecv + pClient->nWriteOffset, 1, 0);if (nRet >= 0){std::cout << "send one char: " << pClient->szRecv[pClient->nWriteOffset] << std::endl;pClient->nWriteOffset += 1;if (pClient->nWriteOffset == pClient->nRecvSize){std::cout << "send finished, close client(" << pClient->strIp.c_str()<< ")" << std::endl;pClient->bNeedWrite = false;closesocket(pClient->hSocket);return false;}return true;}else{int nError = WSAGetLastError();if (WSAEWOULDBLOCK != nError){std::cerr << "send failed with error " << nError << std::endl;closesocket(pClient->hSocket);return false;}std::cout << "next send" << std::endl;return true;}
}int main(int argc, char* argv)
{WORD wVersionRequested = MAKEWORD(2, 2);WSADATA wsaData = { 0 };int err = WSAStartup(wVersionRequested, &wsaData);if (err != 0){return -1;}if (LOBYTE(wsaData.wVersion) != 2 ||HIBYTE(wsaData.wVersion) != 2){WSACleanup();return -1;}SOCKET hListenSocket = socket(AF_INET, SOCK_STREAM, 0);if (INVALID_SOCKET == hListenSocket){std::cerr << "create socket failed with error " << WSAGetLastError()<< std::endl;return -1;}sockaddr_in mSockAddrIn = { 0 };mSockAddrIn.sin_family = AF_INET;mSockAddrIn.sin_port = htons((u_short)8878);mSockAddrIn.sin_addr.S_un.S_addr = inet_addr("0.0.0.0");if (SOCKET_ERROR == bind(hListenSocket, (sockaddr*)(&mSockAddrIn),sizeof(sockaddr))){std::cerr << "bind failed with error " << WSAGetLastError() << std::endl;return -1;}if (SOCKET_ERROR == listen(hListenSocket, SOMAXCONN)){std::cerr << "listen failed with error " << WSAGetLastError() << std::endl;return -1;}std::vector<SOCKET> mAllClients;while (true){fd_set readfds;fd_set writefds;fd_set exceptfds;FD_ZERO(&readfds);FD_ZERO(&writefds);FD_ZERO(&exceptfds);FD_SET(hListenSocket, &readfds);//FD_SET(hListenSocket, &writefds);//FD_SET(hListenSocket, &exceptfds);for (auto it = g_Clients.begin(); it != g_Clients.end(); ++it){std::shared_ptr<ClientSocketItem> pClientItem = *it;if (!pClientItem) continue;FD_SET(pClientItem->hSocket, &readfds);if (pClientItem->bNeedWrite)//否则select会一直有事件{FD_SET(pClientItem->hSocket, &writefds);}FD_SET(pClientItem->hSocket, &exceptfds);}int nRet = select(0, &readfds, &writefds, &exceptfds, nullptr);std::cout << "select return with " << nRet << std::endl;if (nRet > 0){//readif (FD_ISSET(hListenSocket, &readfds)){do_accept(hListenSocket);}for (auto it = g_Clients.begin(); it != g_Clients.end();){std::shared_ptr<ClientSocketItem> pClientItem = *it;if (pClientItem && FD_ISSET(pClientItem->hSocket, &readfds)){if (!do_read(pClientItem)){it = g_Clients.erase(it);continue;}}++it;}//writefor (auto it = g_Clients.begin(); it != g_Clients.end();){std::shared_ptr<ClientSocketItem> pClientItem = *it;if (pClientItem && FD_ISSET(pClientItem->hSocket, &writefds)){if (!do_write(pClientItem)){it = g_Clients.erase(it);continue;}}++it;}//end of for//error for (auto it = g_Clients.begin(); it != g_Clients.end();){std::shared_ptr<ClientSocketItem> pClientItem = *it;if (pClientItem && FD_ISSET(pClientItem->hSocket, &exceptfds)){std::cerr << "client socket except, close and remove it" << std::endl;closesocket(pClientItem->hSocket);it = g_Clients.erase(it);continue;}++it;}//end of for}else{std::cerr << "select failed with error " << WSAGetLastError() << std::endl;}}return 0;
}

相关文章:

测试Winsock的select

说明 实现了一个回显一行字符串的服务器&#xff1a;客户端发送一行字符串&#xff0c;一’\n’结尾&#xff0c;服务器接受完一行后就原封不动地发回给客户端。 windows下对select的能监控的Socket数量是有限制的&#xff0c;若超过&#xff0c;一种方案是再开一个线程。 #i…...

CentOS 搭建 Hadoop3 高可用集群

Hadoop FullyDistributed Mode 完全分布式 spark101spark102spark103192.168.171.101192.168.171.102192.168.171.103namenodenamenodejournalnodejournalnodejournalnodedatanodedatanodedatanodenodemanagernodemanagernodemanagerrecource managerrecource managerjob hist…...

ModuleNotFoundError: No module named ‘paddle.fluid.incubate.fleet‘

在使用rocketqa的时候可能会遇到下面的问题&#xff1a; 问题&#xff1a; 解决方法&#xff1a; 这完全是paddlepaddle的问题。 在rocketqa/utils/optimization.py出现下面的语句&#xff0c;这个时候直接把出错的注释掉就可以&#xff0c;因为它完全没有用到。&#xff08;…...

【Java】Java中的引用类型

强引用&#xff08;StrongReference&#xff09; 通过new直接创建的对象&#xff0c;只要该对象还可以被其它对象使用或访问到&#xff0c;就不会被回收 软引用&#xff08;SoftReference&#xff09; 引用一个对象&#xff0c;该对象在系统内存溢出不足时&#xff0c;会自动…...

File类、方法递归

File:代表文本 IO流&#xff1a;读写数据 1、 File 类构建对象的方式是什么样的&#xff1f; File 的对象可以代表哪些东西&#xff1f; 注意 File 对象既可以代表文件、也可以代表文件夹。 ● File 封装的对象仅仅是一个路径名&#xff0c;这个路径可以是存在的&#xff0c…...

MySQL - 系统库之 sys

sys 系统库用于管理和监控MySQL服务器的性能和运行状态&#xff1a; 用途&#xff1a; 性能监控和分析&#xff1a;sys 系统库用于监控MySQL服务器的性能和资源利用情况。它提供了各种视图和函数&#xff0c;用于分析查询性能、资源利用、等待事件等方面的数据。性能调优&…...

GoLong的学习之路(十七)基础工具之Gin框架使用JWT(前后端分离)

文章目录 JWT安装JWT使用什么是Claims默认Claims自定义Claims生成JWT解析JWT 在gin框架中使用JWT获取Token渠道定义方法设置中间件注册路由 总结一下 JWT JWT全称JSON Web Token是一种跨域认证解决方案&#xff0c;属于一个开放的标准&#xff0c;它规定了一种Token实现方式&a…...

【代码数据】2023粤港澳大湾区金融数学建模B题分享

基于中国特色估值体系的股票模型分析和投资策略 首先非常建议大家仔细的阅读这个题的题目介绍&#xff0c;还有附赠的就是那个附件里的那几篇材料&#xff0c;我觉得你把这些内容读透理解了&#xff0c;就可以完成大部分内容。然后对于题目里它主要第一部分给出了常用的估值模…...

大数据之LibrA数据库系统告警处理(ALM-12006 节点故障)

告警解释 Controller按30秒周期检测NodeAgent状态。当Controller连续三次未接收到某个NodeAgent的状态报告时&#xff0c;产生该告警。 当Controller可以正常接收时&#xff0c;告警恢复。 告警属性 告警ID 告警级别 可自动清除 12006 严重 是 告警参数 参数名称 参…...

poi兴趣点推荐数据集介绍

介绍 foursquare数据集包含2153471个用户&#xff0c;1143092个场所&#xff0c;1021970个签到&#xff0c;27098490个社交关系以及用户分配给场所的2809581评级&#xff0c;我们常用的是根据NYC和TKY都是从该数据集中抽取出来的。 下载地址&#xff1a;https://sites.google.…...

把两个4点的结构相加

( A, B )---3*30*2---( 1, 0 )( 0, 1 ) 让网络的输入只有3个节点&#xff0c;训练集中只有5张图片&#xff0c;让A中有4个1&#xff0c;B全是0&#xff0c;排列组合&#xff0c;统计迭代次数并排序。 其中有3个结构 3差值结构 迭代次数 4差值结构 迭代次数 31 3-2 0 1 …...

windows内存取证-中等难度-下篇

上文我们对第一台Target机器进行内存取证&#xff0c;今天我们继续往下学习&#xff0c;内存镜像请从上篇获取&#xff0c;这里不再进行赘述​ Gideon 攻击者访问了“Gideon”&#xff0c;他们向AllSafeCyberSec域控制器窃取文件,他们使用的密码是什么&#xff1f; 攻击者执…...

代码随想录算法训练营第7天|454 四数相加II 383. 赎金信 15.三数之和 18 四数之和

JAVA代码编写 454. 四数相加 II 给你四个整数数组 nums1、nums2、nums3 和 nums4 &#xff0c;数组长度都是 n &#xff0c;请你计算有多少个元组 (i, j, k, l) 能满足&#xff1a; 0 < i, j, k, l < nnums1[i] nums2[j] nums3[k] nums4[l] 0 示例 1&#xff1a;…...

负载均衡深度解析:算法、策略与Nginx实践

引言 如今&#xff0c;网站和应用服务面临着巨大的访问流量&#xff0c;如何高效、稳定地处理这些流量成为了一个亟待解决的问题。负载均衡技术因此应运而生&#xff0c;它通过将流量合理分配到多个服务器上&#xff0c;不仅优化了资源的利用率&#xff0c;还大大提升了系统的…...

7. 一文快速学懂常用工具——Makefile

本章讲解知识点 引言MakefileMakefile 入门本专栏适合于软件开发刚入职的学生或人士,有一定的编程基础,帮助大家快速掌握工作中必会的工具和指令。本专栏针对面试题答案进行了优化,尽量做到好记、言简意赅。如专栏内容有错漏,欢迎在评论区指出或私聊我更改,一起学习,共同…...

[ACTF2023]复现

MDH 源题&#xff1a; from hashlib import sha256 from secret import flagr 128 c 96 p 308955606868885551120230861462612873078105583047156930179459717798715109629 Fp GF(p)def gen():a1 random_matrix(Fp, r, c)a2 random_matrix(Fp, r, c)A a1 * a2.Treturn…...

HNU-编译原理-讨论课1

讨论课安排&#xff1a;2次4学时&#xff0c;分别完成四大主题讨论 分组&#xff1a;每个班分为8组&#xff0c;每组4~5人&#xff0c;自选组长1人 要求和说明&#xff1a; 以小组为单位上台报告&#xff1b;每次每组汇报2个小主题&#xff0c;每组按要求在2个小主题中各选1…...

【Linux】关于Nginx的详细使用,部署项目

前言&#xff1a; 今天小编给大家带来的是关于Nginx的详细使用&#xff0c;部署项目&#xff0c;希望可以给正在学习&#xff0c;工作的你带来有效的帮助&#xff01; 一&#xff0c;Nginx简介 Nginx是一个高性能的开源Web服务器和反向代理服务器。它最初由Igor Sysoev在2004年…...

编写 navigation2 控制器插件

简介 本教程展示了如何创建自己的控制器插件。在本教程中&#xff0c;我们将基于这篇论文实现纯追踪路径跟踪算法。建议您阅读该论文。   注意&#xff1a;本教程基于 Nav2 堆栈中以前存在的简化版本的 Regulated Pure Pursuit 控制器。您可以在此处找到与本教程相匹配的源代…...

计算机网络 第六章应用层

文章目录 1 应用层功能概述2 网络应用模型&#xff1a;客户服务器(CS)3 网络应用模型&#xff1a;PeerToPeer(P2P)4 域名和域名系统5 常见域名解析服务器6 两种域名解析过程7 什么是FTP8 FTP的工作原理9 EMail的组成 1 应用层功能概述 2 网络应用模型&#xff1a;客户服务器(CS…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

shell脚本--常见案例

1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件&#xff1a; 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

【机器视觉】单目测距——运动结构恢复

ps&#xff1a;图是随便找的&#xff0c;为了凑个封面 前言 在前面对光流法进行进一步改进&#xff0c;希望将2D光流推广至3D场景流时&#xff0c;发现2D转3D过程中存在尺度歧义问题&#xff0c;需要补全摄像头拍摄图像中缺失的深度信息&#xff0c;否则解空间不收敛&#xf…...

学校招生小程序源码介绍

基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码&#xff0c;专为学校招生场景量身打造&#xff0c;功能实用且操作便捷。 从技术架构来看&#xff0c;ThinkPHP提供稳定可靠的后台服务&#xff0c;FastAdmin加速开发流程&#xff0c;UniApp则保障小程序在多端有良好的兼…...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成&#xff0c;用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机&#xff1a; ​onCreate()​​ ​调用时机​&#xff1a;Activity 首次创建时调用。​…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言&#xff1a; 在Java编程中&#xff0c;类的生命周期是指类从被加载到内存中开始&#xff0c;到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期&#xff0c;让读者对此有深刻印象。 目录 ​…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)

考察一般的三次多项式&#xff0c;以r为参数&#xff1a; p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]&#xff1b; 此多项式的根为&#xff1a; 尽管看起来这个多项式是特殊的&#xff0c;其实一般的三次多项式都是可以通过线性变换化为这个形式…...

django blank 与 null的区别

1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是&#xff0c;要注意以下几点&#xff1a; Django的表单验证与null无关&#xff1a;null参数控制的是数据库层面字段是否可以为NULL&#xff0c;而blank参数控制的是Django表单验证时字…...