利用WSAEventSelect进行网络通信

2023-12-07 10:32

本文主要是介绍利用WSAEventSelect进行网络通信,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

              服务器端代码

      

// Server.cpp : 定义控制台应用程序的入口点。
//#include<winsock2.h>
#pragma comment(lib,"WS2_32")
#include<stdio.h>int main()
{printf("服务器程序\n");//加载动态链接库WORD ver=MAKEWORD(2,2);WSADATA data;if(WSAStartup(ver,&data)!=0){printf("WSASTARTUP fail\n");return 1;}else{printf("加载winsock库成功\n");}//创建监听套接字SOCKET s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);u_long u=1;ioctlsocket(s,FIONBIO,&u);//绑定套接字sockaddr_in Sadd;Sadd.sin_family=AF_INET;Sadd.sin_port=htons(6000);Sadd.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");if(bind(s,(sockaddr*)&Sadd,sizeof(Sadd))==SOCKET_ERROR){printf("failed bind()\n");return 1;}else{printf("绑定成功\n");}//监听状态if(listen(s,5)==SOCKET_ERROR){printf("监听失败\n");return 1;}else{printf("监听成功\n");}//创建事件对象WSAEVENT newEvent=WSACreateEvent();if(newEvent==WSA_INVALID_EVENT){printf("创建事件对象失败\n");return 1;}else {printf("创建事件对象成功\n");}//网络事件注册int err=WSAEventSelect(s,newEvent,FD_ACCEPT|FD_CLOSE);if(err==INVALID_SOCKET){printf("注册网络事件失败\n");return 1;}//准备工作int t=1;WSAEVENT eventArray[10];SOCKET sockArray[10];int n=0;eventArray[n]=newEvent;sockArray[n]=s;n++;//循环处理while(true){int index=WSAWaitForMultipleEvents(n,eventArray,false,4000,false);printf("index=%d\n",index);if(index==WSA_WAIT_FAILED){printf("调用失败\n");break;}else if(index==WSA_WAIT_TIMEOUT){if(t<3){printf("第%d次超时",t);t++;continue;}else{printf("第%d次超时,退出",t);break;}}else{WSANETWORKEVENTS events;  //记录网络事件出错的代码//网络事件查询WSAEnumNetworkEvents(sockArray[index],NULL,&events);WSAResetEvent(eventArray[index]);//处理accept消息if((events.lNetworkEvents & FD_ACCEPT)!=0){if(events.iErrorCode[FD_ACCEPT_BIT]==0){if(n>10){printf("连接已经饱满\n");break;}printf("有连接请求到来\n");SOCKET sNew=accept(sockArray[index],NULL,NULL);newEvent=WSACreateEvent();WSAEventSelect(sNew,newEvent,FD_READ|FD_WRITE|FD_CLOSE);eventArray[n]=newEvent;sockArray[n]=sNew;n++;printf("socket %d connect\n",sNew);}}if(events.lNetworkEvents& FD_READ){if(events.iErrorCode[FD_READ_BIT]==0){char buf[256]={0};int num=recv(sockArray[index],buf,sizeof(buf),0);if(num>0){printf("接收到客户端%d的数据:%s\n",sockArray[index],buf);}}}if(events.lNetworkEvents& FD_CLOSE){if(events.iErrorCode[FD_CLOSE_BIT]==0){printf("套接字为%d的已关闭连接\n",sockArray[index]);}else{if(events.iErrorCode[FD_CLOSE_BIT]==10053){printf("客户端%d非法关闭\n",sockArray[index]);}}for(int j=index;j<n-1;j++){eventArray[j]=eventArray[j+1];sockArray[j]=sockArray[j+1];}n--;}}}return 0;
}
客户端代码


//Client 1
#include <winsock2.h>
#pragma comment(lib,"WS2_32")
#include <stdio.h>
int main()
{  	printf("客户端程序\n"); 	
//----------------①加载---------------------------------------------------------WSADATA wsaData;WORD wVersionRequested=MAKEWORD(2,2);  if(WSAStartup(wVersionRequested,&wsaData)!=0)  			{   printf("WSAStartup() Failed,Error=\n",WSAGetLastError());	return 1;}else printf("①加载成功\n");		
//----------------②创建流式套节字------------------------------------------------	SOCKET c1;c1 = socket(AF_INET, SOCK_STREAM,0);if(c1 == INVALID_SOCKET)	{   printf("socket() Failed,Error=\n",WSAGetLastError());return 1;}else printf("②已创建连接套接字:【 %d 】\n",c1);	
//----------------绑定本地地址------------------------------------------------struct  sockaddr_in  C1add;  C1add.sin_family=AF_INET;C1add.sin_port=htons(2222);C1add.sin_addr.s_addr=inet_addr("127.0.0.1");	if(bind(c1,(sockaddr*)&C1add,sizeof(C1add))==SOCKET_ERROR)	{   printf("bind() Failed,Error=\n",WSAGetLastError());	return 1;}else printf("绑定成功,本地IP地址:【 %s 】,端口号:【 %d 】\n",inet_ntoa(C1add.sin_addr),ntohs(C1add.sin_port));	
//------------------③连接请求------------------------------------------------		struct  sockaddr_in  Sadd;  Sadd.sin_family=AF_INET;Sadd.sin_port=htons(6000);  Sadd.sin_addr.s_addr=inet_addr("127.0.0.1");		if(connect(c1, (sockaddr*)&Sadd, sizeof(Sadd)) == -1){   printf(" Failed connect(),Error=【 %d 】\n",WSAGetLastError());		return 1;}else //*************************连接成功,可以 开始发送、接收*************************{	printf("③连接成功,服务器IP地址:【 %s 】,端口号:【 %d 】\n",inet_ntoa(Sadd.sin_addr),ntohs(Sadd.sin_port));int a;printf("希望发送数据吗?(键入“1”发送)");scanf("%d",&a);	 			while(a==1)  //------循环处理------{   //-----发送------     			    char S_buf[] = "Hello!I am a client 1";	int  isend=send(c1,S_buf,strlen(S_buf),0);		if(isend==SOCKET_ERROR)	{  printf("Failed  send(),Error=【 %d 】,或者服务器意外关闭\n",WSAGetLastError());return 1;}else if(isend!=0)printf("信息【 %s 】已发送\n",S_buf);			 elseprintf("信息无法发送给服务端\n");printf("希望继续发送数据吗?(键入“1”继续发送)");scanf("%d",&a);if(a!=1)			break;} //------end 循环处理------	   } //*************************end 开始发送、接收*************************
//------------------④关闭、释放------------------------------------------------	closesocket(c1);		WSACleanup();printf("④与服务器连接完毕\n");return 0;}


这篇关于利用WSAEventSelect进行网络通信的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/465531

相关文章

JAVA SpringBoot集成Jasypt进行加密、解密的详细过程

《JAVASpringBoot集成Jasypt进行加密、解密的详细过程》文章详细介绍了如何在SpringBoot项目中集成Jasypt进行加密和解密,包括Jasypt简介、如何添加依赖、配置加密密钥... 目录Java (SpringBoot) 集成 Jasypt 进行加密、解密 - 详细教程一、Jasyp

linux实现对.jar文件的配置文件进行修改

《linux实现对.jar文件的配置文件进行修改》文章讲述了如何使用Linux系统修改.jar文件的配置文件,包括进入文件夹、编辑文件、保存并退出编辑器,以及重新启动项目... 目录linux对.jar文件的配置文件进行修改第一步第二步 第三步第四步总结linux对.jar文件的配置文件进行修改第一步进

Go语言中如何进行数据库查询操作

《Go语言中如何进行数据库查询操作》在Go语言中,与数据库交互通常通过使用数据库驱动来实现,Go语言支持多种数据库,如MySQL、PostgreSQL、SQLite等,每种数据库都有其对应的官方或第三... 查询函数QueryRow和Query详细对比特性QueryRowQuery返回值数量1个:*sql

Python进行word模板内容替换的实现示例

《Python进行word模板内容替换的实现示例》本文介绍了使用Python自动化处理Word模板文档的常用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友... 目录技术背景与需求场景核心工具库介绍1.获取你的word模板内容2.正常文本内容的替换3.表格内容的

Git进行版本控制的实战指南

《Git进行版本控制的实战指南》Git是一种分布式版本控制系统,广泛应用于软件开发中,它可以记录和管理项目的历史修改,并支持多人协作开发,通过Git,开发者可以轻松地跟踪代码变更、合并分支、回退版本等... 目录一、Git核心概念解析二、环境搭建与配置1. 安装Git(Windows示例)2. 基础配置(必

Nginx中配置使用非默认80端口进行服务的完整指南

《Nginx中配置使用非默认80端口进行服务的完整指南》在实际生产环境中,我们经常需要将Nginx配置在其他端口上运行,本文将详细介绍如何在Nginx中配置使用非默认端口进行服务,希望对大家有所帮助... 目录一、为什么需要使用非默认端口二、配置Nginx使用非默认端口的基本方法2.1 修改listen指令

MySQL按时间维度对亿级数据表进行平滑分表

《MySQL按时间维度对亿级数据表进行平滑分表》本文将以一个真实的4亿数据表分表案例为基础,详细介绍如何在不影响线上业务的情况下,完成按时间维度分表的完整过程,感兴趣的小伙伴可以了解一下... 目录引言一、为什么我们需要分表1.1 单表数据量过大的问题1.2 分表方案选型二、分表前的准备工作2.1 数据评估

MySQL进行分片合并的实现步骤

《MySQL进行分片合并的实现步骤》分片合并是指在分布式数据库系统中,将不同分片上的查询结果进行整合,以获得完整的查询结果,下面就来具体介绍一下,感兴趣的可以了解一下... 目录环境准备项目依赖数据源配置分片上下文分片查询和合并代码实现1. 查询单条记录2. 跨分片查询和合并测试结论分片合并(Shardin

SpringBoot结合Knife4j进行API分组授权管理配置详解

《SpringBoot结合Knife4j进行API分组授权管理配置详解》在现代的微服务架构中,API文档和授权管理是不可或缺的一部分,本文将介绍如何在SpringBoot应用中集成Knife4j,并进... 目录环境准备配置 Swagger配置 Swagger OpenAPI自定义 Swagger UI 底

基于Python Playwright进行前端性能测试的脚本实现

《基于PythonPlaywright进行前端性能测试的脚本实现》在当今Web应用开发中,性能优化是提升用户体验的关键因素之一,本文将介绍如何使用Playwright构建一个自动化性能测试工具,希望... 目录引言工具概述整体架构核心实现解析1. 浏览器初始化2. 性能数据收集3. 资源分析4. 关键性能指