【C++网络编程】(一)Linux平台下TCP客户/服务端程序

文章目录

  • Linux平台下TCP客户/服务端程序
    • 服务端
    • 客户端
    • 相关头文件介绍

Linux平台下TCP客户/服务端程序


图片来源:https://subingwen.cn/linux/socket/

下面实现一个Linux平台下TCP客户/服务端程序:客户端向服务器发送:“你好,服务器…递增数字”,然后服务器发送响应消息:“你好,客户端”。
在这里插入图片描述

服务端

server.cpp

#include <iostream>    
#include <cstdlib>      // std::exit
#include <cstring>      // memset sprintf strlen
#include <arpa/inet.h>  // inet_ntop, htons, ntohs, INADDR_ANY, INET_ADDRSTRLEN 
#include <unistd.h>     // close
// #include <sys/socket.h> // sockaddr_in,  socket(),  bind(), listen(), accept(), send(), recv(),SOCK_STREAM,AF_INET
/*
<arpa/inet.h>包含了<netinet/in.h>,而<netinet/in.h>包含了 <sys/socket.h>。
所以实际使用时,只需要#include <arpa/inet.h>,不需要#include <sys/socket.h> 
*/int main()
{// 1. 创建监听的套接字int lfd = socket(AF_INET, SOCK_STREAM, 0);  // 创建一个TCP套接字if (lfd == -1){perror("socket");  // 错误处理std::exit(EXIT_FAILURE);}// 2. 将socket()返回值和本地的IP端口绑定到一起sockaddr_in addr;  // 用于存储地址信息addr.sin_family = AF_INET; // 地址族,IPv4addr.sin_port = htons(10000);   // 大端端口转换//addr.sin_addr.s_addr = INADDR_ANY;  // 绑定到任意IP地址inet_pton(AF_INET, "172.31.108.107", &addr.sin_addr.s_addr); // 指定IP地址int ret = bind(lfd, (sockaddr*)&addr, sizeof(addr)); // 绑定套接字到地址if (ret == -1){perror("bind");  // 错误处理std::exit(EXIT_FAILURE);}// 3. 设置监听ret = listen(lfd, 128);  // 开始监听if (ret == -1){perror("listen");  // 错误处理std::exit(EXIT_FAILURE);}// 4. 阻塞等待并接受客户端连接sockaddr_in cliaddr; // 用于存储客户端地址信息socklen_t clilen = sizeof(cliaddr);  // 客户端地址结构的大小int cfd = accept(lfd, (sockaddr*)&cliaddr, &clilen); // 接受客户端连接if (cfd == -1){perror("accept");  // 错误处理std::exit(EXIT_FAILURE);}// 打印客户端的地址信息char ip[INET_ADDRSTRLEN] = {0};  // 存储客户端IP地址std::cout << "客户端的IP地址: " << inet_ntop(AF_INET, &cliaddr.sin_addr.s_addr, ip, sizeof(ip))  // 将IP地址转换为字符串<< ", 端口: " << ntohs(cliaddr.sin_port) << std::endl;  // 端口号转换// 5. 和客户端通信while (true){// 接收数据char buf[1024];  // 接收缓冲区memset(buf, 0, sizeof(buf));  // 清零缓冲区int len = recv(cfd, buf, sizeof(buf), 0);  // 从客户端读取数据if (len > 0){std::cout << "客户端: " << buf << std::endl;  // 打印客户端发送的消息sprintf(buf, "你好, 客户端\n");  // 格式化字符串send(cfd, buf, strlen(buf), 0);  // 回应客户端}else if (len == 0){std::cout << "客户端断开了连接..." << std::endl;  // 客户端断开连接break;}else{perror("recv");  // 错误处理break;}}close(cfd);  // 关闭与客户端的连接close(lfd);  // 关闭监听套接字return 0;
}

编译与运行

g++ server.cpp -o server
./server

客户端

client.cpp

#include <iostream>     // std::cout, std::cerr
#include <cstdlib>     // std::exit
#include <unistd.h>     // close, sleep
#include <cstring>      // memset, strlen
#include <arpa/inet.h>  // socket, connect, inet_pton, htonsint main()
{// 1. 创建通信的套接字int fd = socket(AF_INET, SOCK_STREAM, 0);  // 创建一个TCP套接字if (fd == -1){perror("socket");  // 错误处理std::exit(EXIT_FAILURE);}// 2. 连接服务器sockaddr_in addr;  // 用于存储服务器地址信息addr.sin_family = AF_INET; // 地址族,IPv4addr.sin_port = htons(10000);   // 大端端口转换inet_pton(AF_INET, "172.31.108.107", &addr.sin_addr.s_addr); // 将IP地址转换为网络字节顺序int ret = connect(fd, (sockaddr*)&addr, sizeof(addr)); // 连接到服务器if (ret == -1){perror("connect");  // 错误处理std::exit(EXIT_FAILURE);}// 3. 和服务器端通信int number = 0;while (true){// 发送数据char buf[1024];  // 数据缓冲区sprintf(buf, "你好, 服务器...%d", number++);  // 格式化字符串send(fd, buf, strlen(buf), 0);  // 发送数据// 接收数据memset(buf, 0, sizeof(buf));  // 清空缓冲区int len = recv(fd, buf, sizeof(buf), 0);  // 从服务器读取数据if (len > 0){std::cout << "服务器: " << buf;  // 打印服务器发送的消息}else if (len == 0){std::cout << "服务器断开了连接..." << std::endl;  // 服务器断开连接break;}else{perror("recv");  // 错误处理break;}sleep(1);   // 每隔1秒发送一条数据}close(fd);  // 关闭套接字return 0;
}

编译与运行

g++ client.cpp -o client
./client

相关头文件介绍

  1. <cstdlib> :提供了一些常用的标准库函数,源自 C 的 stdlib.h,这些函数与程序控制、内存分配、随机数生成等功能相关。使用到的函数:

    • std::exit(int status):终止程序执行,status 用来返回退出状态码,0 表示正常退出,非 0 表示异常退出。 无返回值,直接终止程序。
  2. <cstring>:是对 C 语言 string.h 的封装,提供了用于操作 C 风格字符串(以 '\0' 结尾的字符数组)和内存操作的函数。使用到的函数:

    • ptr = memset(void* ptr, int value, size_t num):将指定内存区域的前 num 个字节设置为 value。 返回指向 ptr 的指针,即被修改的内存区域的起始地址。
    • n = sprintf(char* buffer, const char* format, ...):将格式化数据写入 buffer,并返回写入的字符数。返回写入 buffer 中的字符数(不包括终止符 '\0')。
    • len = strlen(const char* str):返回 C 风格字符串 str 的长度(不包括终止符 '\0')。 返回 str 的长度。
  3. <arpa/inet.h>:提供了一些用于网络编程的工具函数,主要用于 IP 地址与主机字节序、网络字节序的转换。使用到的函数和宏:

    • inet_ntop(int af, const void* src, char* dst, socklen_t size):将网络格式(大端序)的二进制 IP 地址转换为可读的点分十进制或冒号分隔的字符串。
    • inet_pton(int af, const char* src, void* dst):将可读的点分十进制或冒号分隔的字符串格式的 IP 地址转换为网络格式(大端序)的二进制格式。
    • netshort = htons(uint16_t hostshort):将主机字节序(小端序)的 16 位数转换为网络字节序(大端序)。 返回转换后的网络字节序的 16 位数。
    • hostshort = ntohs(uint16_t netshort):将网络字节序的 16 位数转换为主机字节序。 返回转换后的主机字节序的 16 位数。
    • INADDR_ANY:用于表示绑定到所有可用的本地接口(IP 地址为 0.0.0.0)。
    • INET_ADDRSTRLEN 是一个常量,表示用于存储 IPv4 地址的字符串格式的最大长度。其值通常为 16,这是因为 IPv4 地址的最坏情况是点分十进制表示的字符串形式,如 “255.255.255.255”,该字符串的长度为 15,加上一个字符串终止符 ‘\0’,总共为 16。
  4. <sys/socket.h>:提供了与套接字编程相关的函数和数据结构,定义了套接字的创建、绑定、监听、接受连接、数据收发等功能。使用到的函数、宏和结构体:

    • sockfd = socket(int domain, int type, int protocol):创建一个套接字,domain 表示协议族(如 IPv4 , IPv6),type 表示套接字类型(如 SOCK_STREAM 表示 TCP),protocol 通常为 0,表示默认协议。 返回新的套接字描述符,失败时返回 -1
    • result = bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen):将套接字绑定到特定地址(IP 和端口)。 返回 0 表示成功,返回 -1 表示出错。
    • result = listen(int sockfd, int backlog):将套接字设置为监听模式,backlog 表示队列中可以等待的最大连接数。 返回 0 表示成功,返回 -1 表示出错。
    • new_sockfd = accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen):接受连接请求,并返回一个新的套接字,失败时返回 -1
    • bytes_sent = send(int sockfd, const void* buf, size_t len, int flags):通过连接的套接字发送数据。 返回成功发送的字节数,失败时返回 -1
    • bytes_received = recv(int sockfd, void* buf, size_t len, int flags):从连接的套接字接收数据。 返回成功接收的字节数,返回 0 表示对方关闭连接,失败时返回 -1
    • AF_INET: 是一个常量,用于指定地址族,表示使用 IPv4 地址。
    • SOCK_STREAM:是一个常量,用于指定套接字类型,表示该套接字将使用 TCP 协议进行流式数据传输。
    • sockaddr_in:专门用于 IPv4 地址的结构体,包含 sin_family(地址族)、sin_port(端口号)、sin_addr(IP 地址)等字段。
      struct sockaddr_in {short int          sin_family;   // 地址族unsigned short int sin_port;     // 端口号 (网络字节序)struct in_addr     sin_addr;     // IP 地址unsigned char      sin_zero[8];  // 填充字段(未使用)
      };
      
  5. <unistd.h>:是 Unix-like 操作系统的头文件,提供了对系统调用的访问接口,包含文件操作、进程管理等低级功能。使用到的函数:

    • result = close(int fd):关闭文件描述符 fd,在网络编程中用于关闭套接字。 返回 0 表示成功,返回 -1 表示出错。
    • sleep(unsigned int seconds) :暂停执行当前线程 seconds 秒。

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

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

相关文章

从零创建苹果App应用,不知道怎么申请证书的可以先去看我的上一篇文章

用大家自己的开发者账户&#xff0c;登录进入App Store Connect ,注册自己的应用 进入之后&#xff0c;点击增加 填写相关的信息 一切顺利的话&#xff0c;就可以来到这个页面

element plus的el-select分页

摘要&#xff1a; el-select的数据比较多的时候&#xff0c;必须要分页&#xff0c;处理方案有全部数据回来&#xff0c;或者添加搜索功能&#xff0c;但是就有个问题就是编辑的时候回显问题&#xff0c;必须要保证select的数据有对应的id与name匹配回显&#xff01; <el-fo…

计算机网络-VRRP实验配置

前面我们大致学习了VRRP的概念和基本原理&#xff0c;但是网络这块就是要多敲命令多用才能印象深刻&#xff0c;今天开始进行一些实验配置&#xff0c;结合日常工作的场景分析VRRP在实际工作中的应用。 一、典型VRRP虚拟网关拓扑 相比于传统单网关&#xff0c;采用VRRP虚拟网关…

Qt/C++编写的mqtt调试助手使用说明

一、使用说明 第一步&#xff0c;选择协议前缀&#xff0c;可选mqtt://、mqtts://、ws://、wss://四种&#xff0c;带s结尾的是走ssl通信&#xff0c;ws表示走websocket通信。一般选默认的mqtt://就好。第二步&#xff0c;填写服务所在主机地址&#xff0c;可以是IP地址也可以…

2024.10月11日--- SpringMVC拦截器

拦截器 1 回顾过滤器&#xff1a; Servlet规范中的三大接口&#xff1a;Servlet接口&#xff0c;Filter接口、Listener接口。 过滤器接口&#xff0c;是Servlet2.3版本以来&#xff0c;定义的一种小型的&#xff0c;可插拔的Web组件&#xff0c;可以用来拦截和处理Servlet容…

Python 自动排班表格(代码分享)

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

CentOS安装NVIDIA驱动、CUDA以及nvidia-container-toolkit

0.提前准备 0.1.更新yum源&#xff08;以阿里为例&#xff09; 0.1.1 备份当前的yum源 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup 0.1.2 下载新的CentOS-Base.repo 到/etc/yum.repos.d/ CentOS 5 wget -O /etc/yum.repos.d/CentOS-Base…

ORM框架简介

什么是ORM&#xff1f; ORM&#xff08;Object-Relational Mapping&#xff0c;对象关系映射&#xff09;是一种编程技术&#xff0c;用于在关系数据库和对象程序语言之间转换数据。ORM框架允许开发者以面向对象的方式来操作数据库&#xff0c;而不需要编写复杂的SQL语句。简单…

【Linux】命令行下的增删查改之“查看”

致谢:Linux常用命令大全(手册) – 真正好用的Linux命令在线查询网站 提供的命令查询 头部内容获取(head) head命令的功能是显示文件开头的内容&#xff0c;默认值为前10行。 指令参数&#xff1a; -n 定义显示行数 -c 指定显示头部内容的字符数 -v 总是显示文件名的头信…

告别手动计数:智能统计模型用量,释放设计潜力

添加HanTop-MKT&#xff0c;免费获取统计零件数量模型 非标设备行业的设计BOM因为涉及物料采购与装配数量要求&#xff0c;往往面临着需要数据准确性的严格要求&#xff0c;在缺乏自动化工具情况下&#xff0c;手动统计零件用量变得更加困难&#xff0c;且数据准确性得不到保障…

【uniapp】设置公共样式,实现公共背景等

目录 1、 全局渐变背景色 2.1 创建common目录 2.2 在common下新建style和images等目录 2.3 在style下新建common-style.scss 2.4 common-style输入全局渐变颜色 2.5 引入样式 2.6 业务页面引入 2.7 展示 2、全局字体颜色 2.1 新建base-style.scss文件 2.2 设置base-…

07 django管理系统 - 部门管理 - 搜索部门

在dept_list.html中&#xff0c;添加搜索框 <div class"container-fluid"><div style"margin-bottom: 10px" class"clearfix"><div class"panel panel-default"><!-- Default panel contents --><div clas…

Redis 其他类型 渐进式遍历

我们之前已经学过了Redis最常用的五个类型了&#xff0c;然而Redis还有一些在特定场景下比较好用的类型 Redis最关键的五个数据类型&#xff1a; 上面的类型是非常常用&#xff0c;很重要的类型。 除此之外的其他类型不常用&#xff0c;只是在特定的场景能够发挥用处&#…

无极低码课程【java(jdk)windows下安装及环境变量配置】

在Windows环境中安装JDK 7教程 Java Development Kit (JDK) 是开发Java应用程序所必需的工具包。本教程将指导您在Windows操作系统上安装JDK 7。 准备工作 下载JDK 7安装包 访问 Oracle官方网站 下载JDK 8的安装包。选择适合您操作系统的安装包(例如 jdk-7u80-windows-x64.ex…

vmware虚拟机 报错:客户机操作系统已禁用 CPU,请关闭或重置虚拟机 的解决方法

打开cpu虚拟化全部进行勾选 ctrl e 进行关机 勾选上打开就好了 如果没有那个选项 关机>打开虚拟机>管理>更改硬件兼容性> 往小处改改> >更改此虚拟机

[LeetCode] 515. 在每个树行中找最大值

题目描述&#xff1a; 给定一棵二叉树的根节点 root &#xff0c;请找出该二叉树中每一层的最大值。 示例1&#xff1a; 输入: root [1,3,2,5,3,null,9] 输出: [1,3,9]示例2&#xff1a; 输入: root [1,2,3] 输出: [1,3]提示&#xff1a; 二叉树的节点个数的范围是 [0,10…

基于SpringBoot的个性化健康建议平台

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理基于智能推荐的卫生健康系统的相关信息成为…

OpenTrans

比较的方法Cat-Seg不好复现

Spring 实现 3 种异步流式接口,干掉接口超时烦恼

大家好&#xff0c;我是小富&#xff5e; 如何处理比较耗时的接口&#xff1f; 这题我熟&#xff0c;直接上异步接口&#xff0c;使用 Callable、WebAsyncTask 和 DeferredResult、CompletableFuture等均可实现。 但这些方法有局限性&#xff0c;处理结果仅返回单个值。在某…

幸运7游戏模拟 python

题目&#xff1a; 幸运"7"游戏,用计算机模拟掷骰子的过程&#xff0c;测算两个骰子点数之和为7的概率。 游戏规则是你丢两个骰子&#xff0c;如果其点数之和为7你就赢4元&#xff0c;不是7你就输1元。 假设你刚开始有10元&#xff0c;当全部输掉为0元的时候游戏结…