14.4 Socket 双向数据通信

所谓双向数据传输指的是客户端与服务端之间可以无差异的实现数据交互,此类功能实现的核心原理是通过创建CreateThread()函数多线程分别接收和发送数据包,这样一旦套接字被建立则两者都可以异步发送消息,本章将实现简单的双向交互功能。

首先我们需要封装两个函数,这里RecvFunction函数用于接收数据,SendFunction函数则用于发送数据,这两段代码在服务端与客户端之间是一致的两者可被共用。

#include <iostream>
#include <Winsock2.h> 
#include <windows.h>
#pragma comment (lib, "ws2_32")
#define BUF_SIZE 6400// 接收数据线程
DWORD WINAPI RecvFunction(LPVOID lpParam)
{SOCKET sClient = *(SOCKET*)lpParam;int retVal;char bufRecv[BUF_SIZE];memset(bufRecv, 0, sizeof(bufRecv));while (1){retVal = recv(sClient, bufRecv, BUF_SIZE, 0);if (retVal == SOCKET_ERROR){printf("返回错误 \n");break;}else{printf("收到服务器消息: %s \n", bufRecv);}}return 0;
}// 发送数据线程
DWORD WINAPI SendFunction(LPVOID lpParam)
{SOCKET sClient = *(SOCKET*)lpParam;int retVal;char bufSend[BUF_SIZE];memset(bufSend, 0, sizeof(bufSend));while (1){gets_s(bufSend);retVal = send(sClient, bufSend, strlen(bufSend) + sizeof(char), 0);if (retVal == SOCKET_ERROR){printf("发送错误 \n");break;}}return 0;
}

14.4.1 服务端实现

对于服务端代码而言,一旦accept函数接收到有客户端连接后则自动将该sClient指针传输到子线程内执行,这样即可实现两者功能互不干扰。程序中通过使用CreateThread函数创建了两个线程来处理与客户端之间的发送和接收数据。将SendFunctionRecvFunction作为参数传递给线程,并与新的客户端套接字一起传递。线程存储在变量hThread1hThread2中。

int main(int argc, char* argv[])
{// 初始化套接字动态库WSADATA wsaData;if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){return 1;}//  创建服务段套接字SOCKET sServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (sServer == INVALID_SOCKET){WSACleanup();return -1;}//  服务端地址sockaddr_in addrServ;addrServ.sin_family = AF_INET;addrServ.sin_port = htons(9999);addrServ.sin_addr.s_addr = htonl(INADDR_ANY);//  绑定套接字if (bind(sServer, (const struct sockaddr*)&addrServ, sizeof(addrServ)) == SOCKET_ERROR){closesocket(sServer);WSACleanup();return -1;}//  监听套接字if (listen(sServer, 5) == SOCKET_ERROR){closesocket(sServer);WSACleanup();return -1;}SOCKET sClient;sockaddr_in addrClient;int addrClientLen = sizeof(addrClient);// 接收数据sClient = accept(sServer, (sockaddr FAR*) & addrClient, &addrClientLen);if (sClient == INVALID_SOCKET){closesocket(sServer);WSACleanup();return -1;}printf("接收客户端 IP:[%s] --> port:[%d] \n", inet_ntoa(addrClient.sin_addr), ntohs(addrClient.sin_port));// 分配线程HANDLE hThread1, hThread2;hThread1 = CreateThread(NULL, NULL, SendFunction, (LPVOID*)&sClient, 0, 0);hThread2 = CreateThread(NULL, NULL, RecvFunction, (LPVOID*)&sClient, 0, 0);WaitForSingleObject(hThread1, INFINITE);WaitForSingleObject(hThread2, INFINITE);CloseHandle(hThread1);CloseHandle(hThread2);closesocket(sClient);WSACleanup();return 0;
}

14.4.2 客户端实现

客户端的实现与服务端保持一致,唯一的区别在于客户端通过connect()主动向服务端发送连接请求,只要有新的连接被建立则将通过CreateThread函数创建线程,SendFunctionRecvFunction函数分别用于发送与接收功能。

int main(int argc, char* argv[])
{WSADATA wsaData;// 初始化库if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){return 1;}//  服务器套接字SOCKET sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (sHost == INVALID_SOCKET){WSACleanup();return -1;}SOCKADDR_IN servAddr;servAddr.sin_family = AF_INET;servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");servAddr.sin_port = htons(9999);//  连接服务器if (connect(sHost, (LPSOCKADDR)&servAddr, sizeof(servAddr)) == SOCKET_ERROR){closesocket(sHost);WSACleanup();return -1;}printf("连接到服务器 IP:[%s] --> port:[%d] \n", inet_ntoa(servAddr.sin_addr), ntohs(servAddr.sin_port));// 分别创建两个线程HANDLE hThread1, hThread2;hThread1 = CreateThread(NULL, NULL, SendFunction, (LPVOID)&sHost, 0, 0);hThread2 = CreateThread(NULL, NULL, RecvFunction, (LPVOID)&sHost, 0, 0);WaitForSingleObject(hThread1, INFINITE);WaitForSingleObject(hThread2, INFINITE);CloseHandle(hThread1);CloseHandle(hThread2);closesocket(sHost);WSACleanup();return 0;
}

编译并运行这两个程序,读者可自行测试,不论是在服务端还是客户端均可以实现双向数据通信功能,输出效果如下图所示;

本文作者: 王瑞
本文链接: https://www.lyshark.com/post/9fda2a72.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/157944.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

视频美颜SDK,提升企业视频通话质量与形象

在今天的数字时代&#xff0c;视频通话已经成为企业与客户、员工之间不可或缺的沟通方式。然而&#xff0c;由于网络环境、设备性能等因素的影响&#xff0c;视频通话中的画面质量往往难以达到预期效果。为了提升视频通话的质量与形象&#xff0c;美摄美颜SDK应运而生&#xff…

C#,数值计算——数据建模Plog的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { public class Plog { private int ndat { get; set; } private double[] dat { get; set; } private double[] stau { get; set; } private double[] slogtau { get; set; …

如何使用Net2FTP搭建免费web文件管理器打造个人网盘

文章目录 1.前言2. Net2FTP网站搭建2.1. Net2FTP下载和安装2.2. Net2FTP网页测试 3. cpolar内网穿透3.1.Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 1.前言 文件传输可以说是互联网最主要的应用之一&#xff0c;特别是智能设备的大面积使用&#xff0c;无论是个人…

2023年中国尾气净化催化材料产量、需求量及行业市场规模分析[图]

尾气处理催化单元系由催化剂厂商将以催化材料和活性组分物质为主要组成的催化剂涂覆在蜂窝陶瓷或金属等载体上而成&#xff0c;催化剂则起到处理尾气中有害物质的各类化学反应的关键催化作用&#xff0c;主要由稀土材料、氧化铝材料、贵金属材料等催化材料和增强催化材料性能的…

【论文阅读】面向抽取和理解基于Transformer的自动作文评分模型的隐式评价标准(实验结果部分)

方法 结果 在这一部分&#xff0c;我们展示对于每个模型比较的聚合的统计分析当涉及到计算特征和独立的特征组&#xff08;表格1&#xff09;&#xff0c;抽取功能组和对齐重要功能组&#xff08;表格2&#xff09;&#xff0c;并且最后&#xff0c;我们提供从模型比较&#x…

容器化应用程序管理与分发工具集 | 开源专题 No.34

kubernetes/kubernetes Stars: 101.7k License: Apache-2.0 Kubernetes 是一个开源系统&#xff0c;用于管理跨多个主机的容器化应用程序。它提供了部署、维护和扩展应用程序的基本机制。Kubernetes 借鉴了 Google 在大规模运行生产负载方面十五年的经验&#xff0c;并结合了社…

安装Docker(Linux:CentOS)

大家好我是苏麟今安装一下Docker. 安装Docker Docker 分为 CE 和 EE 两大版本。CE 即社区版&#xff08;免费&#xff0c;支持周期 7 个月&#xff09;&#xff0c;EE 即企业版&#xff0c;强调安全&#xff0c;付费使用&#xff0c;支持周期 24 个月。 Docker CE 分为 stab…

linux中单节点安装greenplum数据库

目录 一、安装包准备 二、关闭防火墙 三、安装greenplum依赖包 四、添加配置 五、新建greenplum用户 六、安装greenplum安装包 七、设置环境变量 八、权限互通 九、修改数据库配置文件 十、初始化数据库 十一、配置远程连接文件 十二、说明 一、安装包准备 下载准备…

【Pytorch】深度学习之损失函数

文章目录 二分类交叉熵损失函数交叉熵损失函数L1损失函数MSE损失函数平滑L1(Smooth L1)损失函数目标泊松分布的负对数似然损失KL散度MarginRankingLoss多标签边界损失函数二分类损失函数多分类的折页损失三元组损失HingEmbeddingLoss余弦相似度CTC损失函数参考资料 学习目标&am…

Excel往Word复制表格时删除空格

1.背景 在编写文档&#xff0c;经常需要从Excel往Word里复制表格 但是复制过去的表格前面会出现空格&#xff08;缩进&#xff09; 再WPS中试了很多方法&#xff0c;终于摆脱了挨个删除的困扰 2. WPS排版中删除 选择表格菜单栏-选在【开始】-【排版】选择【更多段落处理】-【段…

一文深入理解高并发服务器性能优化

我们现在已经搞定了 C10K并发连接问题 &#xff0c;升级一下&#xff0c;如何支持千万级的并发连接&#xff1f;你可能说&#xff0c;这不可能。你说错了&#xff0c;现在的系统可以支持千万级的并发连接&#xff0c;只不过所使用的那些激进的技术&#xff0c;并不为人所熟悉。…

2023年中国玉米深加工产能、市场规模、消费量及产品需求结构[图]

玉米深加工顾名思义就是将产业链延长,进而提升产品附加值,利用玉米提炼出酒精、玉米胚芽油、淀粉和饲料等大概两百余种玉米深加工产品。我国是玉米种植大国&#xff0c;也是玉米深加工大国&#xff0c;但是玉米加工行业却长时间处于产能过剩、开工率不足、利润率低下的境况&…

AOMEI PXE Boot Free

两台电脑网线直连&#xff0c;不用设置固定IP&#xff0c;该软件包含DHCP。 名称: 3H3AOMEIPXEBootFree.rar 大小: 13068734 字节 (12 MiB) SHA1: 1e606c8c1ee3badf8af9a87f61fdf2e332b773e6 名称: PXEBoot.exe 大小: 13124928 字节 (12 MiB) SHA1: 95286ac18e9b81c2a68412c40…

【docker - 安装】windows 10 专业版 安装docker,以及 WSL kernel version too low 解决方案

一、开启 Hyper-V 二、下载 docker 三、安装 docker 四、问题 Stage 1&#xff1a;打开 powershell&#xff0c;并执行 Stage 2&#xff1a;下载Linux内核更新包&#xff0c;并安装 Stage 3&#xff1a;将 WSL 2 设置为默认版本 Stage 4&#xff1a;安装所选的 Linux 分…

Qt 输入组控件(Input Widgets) 显示组控件(Display Widgets)详解

一、Qt 输入组控件(Input Widgets&#xff09; Qt Input Widgets是一组用户界面元素&#xff0c;用于输入和显示文字和数字等的数据。这些小部件可以组成各种不同的表单和对话框&#xff0c;用户可以使用这些小部件与程序交互。 以下是Qt Input Widgets的一些常见小部件&…

如何用 ChatGPT 的 Advanced Data Analysis 帮你采集数据?

&#xff08;注&#xff1a;本文为小报童精选文章&#xff0c;已订阅小报童或加入知识星球「玉树芝兰」用户请勿重复付费&#xff09; 想采集网页数据却不会写 Python 爬虫&#xff1f;不会就不会吧&#xff0c;ChatGPT 会就可以了 &#x1f602; 问题描述 朋友最近遇到了一点儿…

互联网Java工程师面试题·Java 并发编程篇·第五弹

目录 52、什么是线程池&#xff1f; 为什么要使用它&#xff1f; 53、怎么检测一个线程是否拥有锁&#xff1f; 54、你如何在 Java 中获取线程堆栈&#xff1f; 55、JVM 中哪个参数是用来控制线程的栈堆栈小的? 56、Thread 类中的 yield 方法有什么作用&#xff1f; 57、…

jwt详细介绍

jwt详细介绍 1.jwt 简介&#xff1a;2.jwt 工具类介绍3.案列演示&#xff1a;3.1并在web.xml进行配置过滤器 3.2过滤3.3全局响应设置 1.jwt 简介&#xff1a; 。JWT&#xff08;JSON Web Token&#xff09; 是一种用于安全传输信息的开放标准&#xff08;RFC 7519&#xff09;…

ue5打包失败与优化项目

打包报错&#xff1a; PackagingResults: Error: Multiple game targets found for project. Specify the desired target using the -Target... argument. 解决方案&#xff1a; 关闭项目后&#xff0c;删除项目目录下的 Intermediate 文件 再重新启动项目打包即可 参考&…

Linux实现原理 — I/O 处理流程与优化手段

Linux I/O 接口 Linux I/O 接口可以分为以下几种类型&#xff1a; 文件 I/O 接口&#xff1a;用于对文件进行读写操作的接口&#xff0c;包括 open()、read()、write()、close()、lseek() 等。 网络 I/O 接口&#xff1a;用于网络通信的接口&#xff0c;包括 socket()、conne…