C++ —— 网络通信

        之前在Linux系统下介绍了多种实现网络通信的方式,从本文开始后面的文章将在Windows系统下用C++为大家介绍技术,敬请期待~。

        话不多说,直接进入正文,我们知道,要完成网络通信要用到非常多的函数,并且函数的参数比较复杂,所以小编在想封装一个network的工具方便后面要写通信的时候直接调用。工具包括一个头文件network.h和一个 .cpp 文件network.cpp。头文件中定义一个NetWork类,成员变量包含了通信要用到的诸如描述符和通信地址的信息;成员函数就是通信过程中用到的函数。

        network.h头文件如下:

#ifndef NETWORK_H
#define NETWORK_H#include <iostream>
#include <sys/types.h>
// #include <sys/socket.h>
// #include <netinet/in.h>
// #include <arpa/inet.h>
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <cstring>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>class NetWork
{int sock;           //socket对象描述符int type;           //协议类型sockaddr_in addr;   //通信地址socklen_t addrlen;  //地址结构字节数bool is_svr;        //是否为服务器端
public:NetWork(void);NetWork(int type,const char *ip,short port,bool is_svr=false);~NetWork(void);bool open(void);NetWork* accept(void);int send(const char *buf,int flag=0);int send(const void *buf,size_t len,int flag=0);int recv(void *buf,size_t len,int flag=0);
};#endif // NETWORK_H

下面要在network.cpp文件中去一一定义NetWork的成员函数,也是工具的主要逻辑所在。为了通用性考虑,我们在NetWork类中专门定义了协议类型type去区分TCP通信和UDP通信协议以及定义了is_svr去区分调用服务器端和客户端,并在函数定义中去判断从而不影响各自的网络通信步骤。

#include "network.h"
using namespace std;NetWork::NetWork(void)
{addrlen = sizeof(addr);type = SOCK_STREAM;is_svr = false;
}NetWork::NetWork(int type, const char *ip, short port, bool is_svr):type(type), is_svr(is_svr)
{// 不在构造函数中创建socket,因为socket创建可能失败,而构造函数是没有返回值的,不能在此创建addr.sin_family = AF_INET;addr.sin_port = htons(port);addr.sin_addr.s_addr = inet_addr(ip);addrlen = sizeof(addr);
}NetWork::~NetWork(void)
{close(sock);
}bool NetWork::open(void)
{WSADATA wsaData;if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){perror("WSADATA失败");}//创建socket对象sock = socket(AF_INET, type, 0);if (sock < 0){perror("socket");return false;}//根据type和is_svr执行以下流程if(is_svr){if(bind(sock, (sockaddr*)&addr, addrlen)){perror("bind");return false;}if(SOCK_STREAM == type && listen(sock, 50)){perror("listen");return false;}}else if(SOCK_STREAM == type && connect(sock, (sockaddr*)&addr, addrlen)){perror("connect");return false;}return true;
}NetWork *NetWork::accept(void) 
{if(SOCK_STREAM!= type || !is_svr){puts("只有type为SOCK_STREAM且为服务端才能调用该函数\n");return NULL;}NetWork *nw = new NetWork;nw->sock = ::accept(sock, (sockaddr*)&nw->addr, &nw->addrlen);if(nw->sock < 0){perror("accept");delete nw;return NULL;}return nw;
}int NetWork::send(const char *buf, int flag) 
{if(SOCK_STREAM == type)return ::send(sock, buf, strlen(buf)+1, flag);elsereturn sendto(sock, buf, strlen(buf)+1, flag, (sockaddr*)&addr, addrlen);
}int NetWork::send(const void *buf, size_t len, int flag) 
{if(SOCK_STREAM == type)return ::send(sock, (const char*)buf, len, flag);elsereturn sendto(sock, (const char*)buf, len, flag, (sockaddr*)&addr, addrlen);
}int NetWork::recv(void *buf, size_t len, int flag) 
{if(SOCK_STREAM == type)return ::recv(sock, (char*)buf, len, flag);elsereturn recvfrom(sock, (char*)buf, len, flag, (sockaddr*)&addr, &addrlen);
}

为了测试工具是否具备以上介绍的功能,我们准备一个TCP客户端和一个服务器进行通信以进行验证:

服务端:

#include "network.h"
using namespace std;#define BUF_SIZE (4096)void *run(void *arg)
{NetWork *cnw = static_cast<NetWork *>(arg);char *buf = new char[BUF_SIZE];while (1){int ret = cnw->recv(buf, BUF_SIZE);if (ret <= 0 || 0 == strcmp(buf, "quit")){puts("客户端退出!\n");delete cnw;delete buf;return NULL;}printf("recv:%s bits:%d\n", buf, ret);strcat(buf, ":return");ret = cnw->send(buf);if (ret <= 0){puts("客户端退出!\n");delete cnw;delete buf;return NULL;}}
}int main(int argc, const char *argv[])
{if (3 != argc){printf("User: server <ip> <port>");return 0;}// WSADATA wsaData;// if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)// {// 	perror("WSADATA失败");// }NetWork *snw = new NetWork(SOCK_STREAM, argv[1], atoi(argv[2]), true);if (!snw->open()){delete snw;return -1;}while (1){NetWork *cnw = snw->accept();if (NULL == cnw){continue;}pthread_t tid;pthread_create(&tid, NULL, run, (void *)cnw);}return 0;
}

客户端:

#include "network.h"
using namespace std;int main(int argc, const char *argv[])
{// WSADATA wsaData;// if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)// {//     perror("WSADATA失败");// }NetWork *cnw = new NetWork(SOCK_STREAM, argv[1], atoi(argv[2]), false);if (!cnw->open()){delete cnw;return -1;}char buf[4096];size_t buf_size = sizeof(buf);while (1){cout << ">>>>>" << endl;cin.getline(buf, buf_size);int ret = cnw->send(buf, strlen(buf) + 1, 0);if (ret <= 0 || 0 == strcmp("quit", buf)){printf("通信结束!\n");delete cnw;break;}ret = cnw->recv(buf, buf_size, 0);if (ret <= 0){delete cnw;break;}printf("recv:%s bits:%d\n", buf, ret);}return 0;
}

下面我们先启动服务器再运行客户端进行测试,测试结果如下:

上图中,左边是服务器端,右边是客户端,可以看到,由客户端发送消息给服务端,服务端可以正常接收消息并响应客户端返回,客户端也可以接收服务器的响应,由此完成通信。

over

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

FPGA视频GTH 8b/10b编解码转PCIE3.0传输,基于XDMA中断架构,提供工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐我已有的PCIE方案我已有的 GT 高速接口解决方案 3、PCIE基础知识扫描4、工程详细设计方案工程设计原理框图输入Sensor之-->芯片解码的HDMI视频数据组包基于GTH高速接口的视频传输架构GTH IP 简介GTH 基本结构GTH 发送和接收处理…

java基础之 String\StringBuffer\ StringBuilder

文章目录 String字符串的创建为什么说String是不可变的&#xff1f;创建后的字符串存储在哪里&#xff1f;字符串的拼接String类的常用方法 StringBuilder & StringBuffer使用方法验证StringBuffer和StringBuilder的线程安全问题 总结三者区别什么情况下用运算符进行字符串…

深度解析阿里的Sentinel

1、前言 这是《Spring Cloud 进阶》专栏的第五篇文章&#xff0c;这篇文章介绍一下阿里开源的流量防卫兵Sentinel&#xff0c;一款非常优秀的开源项目&#xff0c;经过近10年的双十一的考验&#xff0c;非常成熟的一款产品。 文章目录如下&#xff1a; 2、什么是sentinel&…

移远通信推出全星系多频段高精度定位定向GNSS模组LG580P,引领高精度导航新时代

近日&#xff0c;全球领先的物联网整体解决方案供应商移远通信宣布&#xff0c;正式发布其全星系多频段高精度GNSS模组LG580P。该模组具备高精度、高稳定性、低功耗等特点&#xff0c;并支持20Hz RTK Heading 更新频率&#xff0c;为智能机器人、精准农业、测量测绘、自动驾驶…

Python设计模式探究:单例模式实现及应用解析

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storm…

企业微信会话存档引用com.tencent.wework.Finance出错?

报错&#xff1a; 会话存档引用com.tencent.wework.Finance出错&#xff0c;找不到该类&#xff0c;报错如下&#xff1a;java.lang.NoClassDefFoundError: Could not initialize class com.tencent.wework.Finance 这个问题怎么解决&#xff1f; 解决方案&#xff1a;需要下载…

【前端基础】盒子模型

目标&#xff1a;掌握盒子模型组成部分&#xff0c;使用盒子模型布局网页区域 01-选择器 结构伪类选择器 基本使用 作用&#xff1a;根据元素的结构关系查找元素。 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8">…

鸿蒙开发:ArkUI Toggle 组件

ArkUI提供了一套完整的UI开发工具集&#xff0c;帮助开发者高效完成页面的开发。它融合了语言、编译器、图形构建等关键的应用UI开发底座&#xff0c;为应用的UI开发提供了完整的基础设施&#xff0c;包括简洁的UI语法、丰富的UI功能以及实时界面预览工具等&#xff0c;可以支持…

【LeetCode每日一题】——802.找到最终的安全状态

文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时空频度】九【代码实现】十【提交结果】 一【题目类别】 图 二【题目难度】 中等 三【题目编号】 802.找到最终的安全状态 四【题目描述】 有一个有…

安利一款开源企业级的报表系统SpringReport

SpringReport是一款企业级的报表系统&#xff0c;支持在线设计报表&#xff0c;并绑定动态数据源&#xff0c;无需写代码即可快速生成想要的报表&#xff0c;可以支持excel报表和word报表两种格式&#xff0c;同时还可以支持excel多人协同编辑&#xff0c;后续考虑实现大屏设计…

考公人数攀升?地信、测绘、地质、遥感等专业,能报考哪些单位

近年来&#xff0c;考公人数持续飙升&#xff0c;国考报名人数更逐年攀升。2025年国家公务员考试共有341.6万人通过资格审查&#xff0c;报录比达86:1。国考报名人数再创新高。 国家公务员考试时间安排 地理学相关岗位分析 地信属于地理科学类&#xff0c;测绘类中不包括地信&…

LabVIEW 离心泵机组故障诊断系统

开发了一套基于LabVIEW图形化编程语言设计的离心泵机组故障诊断系统。系统利用先进的数据采集技术和故障诊断方法&#xff0c;通过远程在线监测与分析&#xff0c;有效提升了离心泵的预测性维护能力&#xff0c;保证了石油化工生产的连续性和安全性。 项目背景及意义 离心泵作…

YOLOv10改进策略【卷积层】| CVPR-2023 SCConv 空间和通道重建卷积:即插即用,减少冗余计算并提升特征学习

一、本文介绍 本文记录的是利用ScConv优化YOLOv10的目标检测网络模型。深度神经网络中存在大量冗余&#xff0c;不仅在密集模型参数中&#xff0c;而且在特征图的空间和通道维度中。ScConv模块通过联合减少卷积层中空间和通道的冗余&#xff0c;有效地限制了特征冗余&#xff…

Linux 文件系统权限

文件的一般权限 文件详细信息 使用命令 ll 或 ls -l 查看 文件权限构成 权限针对三类对象定义 owner &#xff1a;所有者&#xff0c;缩写 u group &#xff1a;所属组&#xff0c;缩写 g other &#xff1a;其他人&#xff0c;缩写 o 访问者三种权限 组成模式分析 …

C++上机实验|多态性编程练习

1.实验目的 (1)理解多态性的概念。 (2)掌握如何用虚函数实现动态联编 (3)掌握如何利用虚基类。 2.实验内容 设计一个飞机类 plane,由它派生出歼击机类fighter和轰炸机类 bomber,歼击机类fighter 和轰炸机类bomber 又共同派生出歼轰机(多用途战斗机)。利用虚函数和虚基类描述…

学习threejs,使用对象组合

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.Object3D 三维物体 二…

遇到的问题

刚遇到的问题&#xff1a; 一直以为这个图片数据结构是以下这种&#xff1a; {"descrlong1": [{"CL04": "人力违纪"},{"CL05": "其他"}], }其实数据结构是&#xff1a; {"descrlong1": [{"key": &quo…

发现8个高风险漏洞 NVIDIA GeForce用户必须更新GPU驱动程序

所有NVIDIA GeForce图形处理器都面临着高风险&#xff0c;因为该公司在其图形处理器驱动程序中发现了几个漏洞&#xff0c;这些漏洞可能会让黑客利用你的系统。公司敦促用户更新到最新的GeForce显示屏和VGPU驱动程序&#xff0c;以确保他们的系统不受任何漏洞的影响。 NVIDIA在…

Redis 中 Bitmap 原理和应用

Bitmap Redis中的Bitmap&#xff08;位图&#xff09;是一种较为特殊数据类型&#xff0c;它以最小单位bit来存储数据&#xff0c;我们知道一个字节由 8个 bit 组成&#xff0c;和传统数据结构用字节存储相比&#xff0c;这使得它在处理大量二值状态&#xff08;true、false 或…

微信小程序开发,诗词鉴赏app

文章目录 1. 项目功能思维导图2. 项目涉及到的技术点3. 开发环境4. 项目运行效果5. 部分功能实现6. 关于本人其它项目的介绍 1. 项目功能思维导图 2. 项目涉及到的技术点 使用MySQL数据库实现数据存储使用setInterval实现启动页3s倒计时使用storage实现数据持久化存储&#xf…