【C++】使用C++实现基于Socket的通信

在这里插入图片描述

在本文中,我们将详细讨论如何使用C++实现基于Socket的通信,并设计一个TLV(Type-Length-Value)协议用于数据交互。TLV协议因其灵活性和可扩展性,在多种通信协议中被广泛使用,特别是在需要动态定义数据结构的场景中。我们将分步骤实现Socket通信,设计TLV协议,并通过示例代码展示其应用。
在这里插入图片描述

一、Socket通信基础

1.1 Socket简介

Socket是一种网络通信接口,它提供了端到端的通信服务。Socket分为TCP(Transmission Control Protocol,传输控制协议)和UDP(User Datagram Protocol,用户数据报协议)两种类型。TCP是面向连接的、可靠的、基于字节流的传输层通信协议,而UDP则是无连接的、不可靠的、基于数据报的传输层通信协议。

1.2 TCP Socket编程基本步骤

创建Socket:使用socket()函数创建一个新的socket描述符。
绑定Socket:使用bind()函数将socket与特定的IP地址和端口号绑定。
监听连接(服务器端):使用listen()函数使socket进入监听状态,准备接收客户端的连接请求。
接受连接(服务器端):使用accept()函数接受客户端的连接请求,建立连接。
连接服务器(客户端):使用connect()函数与服务器建立连接。
数据读写:使用send()、recv()等函数进行数据的发送和接收。
关闭连接:使用close()函数关闭socket连接。

二、TLV协议设计

TLV(Type-Length-Value)协议是一种简单但强大的数据编码方式,它通过三个主要部分来组织数据:

Type(类型):用于标识Value的类型或用途,通常是一个整数。
Length(长度):表示Value部分的长度,也是一个整数。
Value(值):实际的数据内容,其类型和长度由Type和Length决定。

2.1 TLV数据结构定义

#include <cstdint>  
#include <vector>  
#include <memory>  struct TLVElement {  std::uint16_t type;    // Type部分,通常使用16位整型  std::uint16_t length;  // Length部分,也是16位整型  std::vector<std::uint8_t> value;  // Value部分,使用字节向量存储  // 构造函数、序列化、反序列化等成员函数可以在这里添加  
};  // TLV消息可以看作是一个TLVElement的数组  
using TLVMessage = std::vector<TLVElement>;

2.2 TLV协议的序列化与反序列化

序列化是将TLV消息转换为字节流以便在网络中传输的过程,反序列化则是将接收到的字节流转换回TLV消息的过程。

// 序列化函数示例  
std::vector<std::uint8_t> SerializeTLVMessage(const TLVMessage& message) {  std::vector<std::uint8_t> result;  for (const auto& elem : message) {  // 写入Type  result.push_back(elem.type & 0xFF);  result.push_back((elem.type >> 8) & 0xFF);  // 写入Length  result.push_back(elem.length & 0xFF);  result.push_back((elem.length >> 8) & 0xFF);  // 写入Value  result.insert(result.end(), elem.value.begin(), elem.value.end());  }  return result;  
}  // 反序列化函数需要根据实际情况设计,这里不详细展开

三、C++ Socket编程实现

3.1 服务器端代码实现

#include <iostream>  
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <unistd.h>  
#include <cstring>  // 假设Socket和TLV的序列化/反序列化已经实现  int main() {  int server_fd, new_socket;  struct sockaddr_in address;  int opt = 1;  int addrlen = sizeof(address);  // 创建socket文件描述符  if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {  perror("socket failed");  exit(EXIT_FAILURE);  }  // 强制绑定socket到端口8080  if (setsockopt(server_fd, SOL_SOCKET, SO_REUSE
ADDRPORT, &opt, sizeof(opt))) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(8080);if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0) {  perror("bind failed");  exit(EXIT_FAILURE);  
}  
if (listen(server_fd, 3) < 0) {  perror("listen");  exit(EXIT_FAILURE);  
}  if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) {  perror("accept");  exit(EXIT_FAILURE);  
}  // 假设我们有一个TLVMessage需要发送给客户端  
TLVMessage messageToSend;  
// 填充messageToSend...  // 序列化TLVMessage为字节流  
auto serializedData = SerializeTLVMessage(messageToSend);  // 发送数据  
send(new_socket, serializedData.data(), serializedData.size(), 0);  // 关闭socket  
close(new_socket);  
close(server_fd);  return 0;
}

3.2 客户端代码实现

#include <iostream>  
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>  
#include <unistd.h>  
#include <cstring>  // 假设Socket和TLV的反序列化函数已经实现  int main() {  struct sockaddr_in serv_addr;  int sock = 0;  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {  std::cerr << "Socket creation error" << std::endl;  return -1;  }  serv_addr.sin_family = AF_INET;  serv_addr.sin_port = htons(8080);  // 将IPv4地址从文本转换为二进制形式  if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0) {  std::cerr << "Invalid address/ Address not supported" << std::endl;  return -1;  }  if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {  std::cerr << "Connection Failed" << std::endl;  return -1;  }  // 接收数据  char buffer[1024] = {0};  int valread = read(sock, buffer, 1024);  std::vector<std::uint8_t> receivedData(buffer, buffer + valread);  // 反序列化数据为TLVMessage  TLVMessage receivedMessage = DeserializeTLVMessage(receivedData);  // 处理receivedMessage...  // 关闭socket  close(sock);  return 0;  
}

四、TLV协议在实际应用中的优势与注意事项

4.1 优势

灵活性:TLV协议允许在单个消息中灵活地包含多种类型的数据,每个TLV元素都是独立的,易于扩展和维护。
可扩展性:通过增加新的Type值,可以很容易地添加新的数据类型或功能,而无需修改现有数据的结构。
清晰性:每个TLV元素都明确指出了其类型和长度,这使得数据的解析变得简单明了。

4.2 注意事项

性能:由于每个TLV元素都包含Type和Length字段,这可能会增加消息的开销,特别是在包含大量小元素时。
对齐与填充:在序列化到某些类型的网络或存储设备时,可能需要考虑字节对齐和填充问题,以确保数据的正确性和效率。
错误处理:在反序列化过程中,必须严格检查Type和Length的有效性,以避免数据损坏或安全问题。

五、总结

本文详细讨论了如何使用C++实现基于Socket的通信,并设计了一个TLV协议用于数据交互。我们介绍了Socket编程的基本步骤,包括创建Socket、绑定、监听、接受连接、数据读写和关闭连接等。同时,我们定义了TLV协议的数据结构,并展示了如何将其序列化为字节流以便在网络中

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

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

相关文章

【Axure】产品原型如何在谷歌浏览器中打开

作为一名前端开发来说&#xff0c;在拿到产品的原型图后&#xff0c;如何打开&#xff1f;直接用谷歌浏览器打开&#xff0c;是打不开的&#xff0c;需要安装对应的插件。但是谷歌插件市场在不翻墙的情况下&#xff0c;是没有办法直接打开的&#xff0c;分享一种超级简单的方法…

深入解析RocketMQ的名字服务机制:功能、原理与应用

NameServer 是专为 RocketMQ 设计的轻量级名字服务&#xff0c;它的源码非常精简&#xff0c;八个类 &#xff0c;少于 1000 行代码。 这篇文章&#xff0c; 笔者会从基础概念、Broker 发送心跳包、NameServer 维护路由、Zookeeper vs NameServer 四个模块揭秘名字服务的设计精…

电脑怎样连接打印机?详细步骤告诉你!

在现代办公环境中&#xff0c;打印机是必不可少的设备之一。无论是打印文档、图片还是其他资料&#xff0c;连接打印机都是我们日常工作中的基本操作。然而&#xff0c;不同类型的打印机和连接方式可能会让人感到困惑。本文将介绍电脑怎样连接打印机的3种方法&#xff0c;帮助您…

简易限流实现

需求描述 写一个1秒两个的限流工具类&#xff0c;2r/s 使用semaphore 代码实现-类似令牌桶算法 public class LimitHelper {private int maxLimit;private Semaphore semaphore;private int timeoutSeconds;public LimitHelper(int maxLimit, int timeoutSeconds) {this.max…

LNMP搭建Discuz和Wordpress

1、LNMP L:linux操作系统 N&#xff1a;nginx展示前端页面web服务 M&#xff1a;mysql数据库&#xff0c;保存用户和密码&#xff0c;以及论坛相关的内容 P&#xff1a;php动态请求转发的中间件 数据库的作用&#xff1a; 登录时验证用户名和密码 创建用户和密码 发布和…

昇思25天学习打卡营第十七天|文本解码原理--以MindNLP为例

背景 提供免费算力支持&#xff0c;有交流群有值班教师答疑的华为昇思训练营进入第十七天了。 今天是第十七天&#xff0c;从第十天开始&#xff0c;进入了应用实战阶段&#xff0c;前九天都是基础入门阶段&#xff0c;具体的学习内容可以看链接 基础学习部分 昇思25天学习打卡…

Unity发布webgl之后修改StreamingAssets 内的配置文件读取到的还是之前的配置文件的解决方案

问题描述 unity发布webgl之后&#xff0c;修改在StreamingAssets 中的配置信息&#xff0c;修改之后读取的还是之前的配置信息 读取配置文件的代码IEnumerator IE_WebGL_LoadWebSocketServerCopnfig(){var uri new System.Uri(Path.Combine(Application.streamingAssetsPath…

居家客服人员分散,更需要统一客服话术

1、居家客服服务需求激增 近年来&#xff0c;随着线上消费的兴起&#xff0c;以及客服人员成本的不断攀升&#xff0c;越来越多的企业选择雇佣居家客服&#xff0c;以客服服务发包的形式接待客户的咨询。因此&#xff0c;居家客服人员的数量也逐渐增加。然而&#xff0c;居家办…

c++ 多边形 xyz 数据 获取 中心点方法

有需求需要对。多边形 获取中心点方法&#xff0c;绝大多数都是 puthon和java版本。立体几何学中的知识。 封装函数 point ##########::getCenterOfGravity(std::vector<point> polygon) {if (polygon.size() < 2)return point();auto Area [](point p0, point p1, p…

PHP充电桩小程序系统源码

绿色出行新伴侣&#xff01;充电桩小程序&#xff0c;让充电不再烦恼✨ &#x1f50b; 开篇&#xff1a;告别电量焦虑&#xff0c;充电桩小程序来救场&#xff01; 在这个电动车日益普及的时代&#xff0c;电量不足成了不少车主的“心头大患”。但别担心&#xff0c;充电桩小…

nprogress进度条插件

打开一个页面时&#xff0c;往往会伴随一些请求&#xff0c;并且会在页面上方出现进度条。它的原理时&#xff0c;在我们发起请求的时候开启进度条&#xff0c;在请求成功后关闭进度条&#xff0c;所以只需要在request.js中进行配置。 如下图所示&#xff0c;我们页面加载时发起…

【R语言+Gephi】利用R语言和Gephi实现共发生网络的可视化

【R语言Gephi】利用R语言和Gephi实现共发生网络的可视化 注&#xff1a;本文仅作为自己的学习记录以备以后复习查阅 一 概述 Gephi是一款开源免费的多平台网络分析软件&#xff0c;在Windows、Linux和Mac os上均可以运行&#xff0c;像他们官网所说的&#xff0c;他们致力于…

【深度学习】Pytorch完成线性回归!

&#x1f34a;嗨&#xff0c;大家好&#xff0c;我是小森( &#xfe61;ˆoˆ&#xfe61; )&#xff01; 易编橙终身成长社群创始团队嘉宾&#xff0c;橙似锦计划领衔成员、阿里云专家博主、腾讯云内容共创官、CSDN人工智能领域优质创作者 。 易编橙&#xff1a;一个帮助编程小…

提升困难生学工支持:智慧校园的新功能介绍

智慧校园的学工管理系统内嵌的困难生信息管理功能&#xff0c;是一个综合性的服务平台&#xff0c;专注于精准识别校园内的经济困难学生&#xff0c;并给予他们必要的帮助与关怀&#xff0c;确保每位学生都能在公平的环境中追求学业和个人成长。这一功能通过一系列信息化手段&a…

标准立项 | 深度脱氨生物填料选型指南

编制单位&#xff1a;北京科净源科技股份有限公司、中国地质大学(北京)、中华环保联合会水环境治理专业委员会、清华大学、北京师范大学、中国环境科学研究院、清华大学、天津高端装备研究院、中车环境科技有限公司、云南滇池水务股份有限公司等。

职升网:考取专科学历的途径包括以下这些!

高考统招&#xff1a; 每年6月举行的全国统一高考&#xff0c;是获得专科学历的传统途径。 考生需参加由教育部组织的统一考试&#xff0c;按照分数由高到低依次录取。 适合高中毕业生或具有同等学历的学生。 自学考试&#xff1a; 又称自考&#xff0c;是一种没有入学考试…

C/C++ list模拟

模拟准备 避免和库冲突&#xff0c;自己定义一个命名空间 namespace yx {template<class T>struct ListNode{ListNode<T>* _next;ListNode<T>* _prev;T _data;};template<class T>class list{typedef ListNode<T> Node;public:private:Node* _…

ArcGIS的智慧与情怀

初识ArcGIS 在这个信息化的时代&#xff0c;ArcGIS如同一位智者&#xff0c;静静地伫立在地理信息系统的巅峰。初识它时&#xff0c;我仿佛走进了一片未知的领域&#xff0c;心中充满了好奇与期待。ArcGIS&#xff0c;这款专业的地理信息系统软件&#xff0c;凭借其强大的功能…

小米恢复联系人,跟着这2个步骤,让你的社交重回巅峰

当你突然发现小米手机里的联系人列表变得空空如也&#xff0c;是不是感觉就像失去了与外界沟通的“秘密武器”&#xff1f;别担心&#xff0c;这并不意味着你真的失去了他们。他们可能只是藏在了手机里的某个神秘角落&#xff0c;等待着你的召唤。接下来&#xff0c;小编将会介…

瓦罗兰特游戏帧数低怎么办 瓦罗兰特游戏帧率提不上去怎么解决

瓦罗兰特是一款由拳头游戏&#xff08;Riot Games&#xff09;开发的5v5英雄射击游戏。结合了MOBA元素&#xff0c;每个角色都拥有四个独特的技能&#xff1b;提供了多种游戏模式&#xff0c;如5V5战术射击等&#xff1b;角色和皮肤设计丰富。游戏中&#xff0c;玩家将扮演各具…