Socket编程-tcp

news2025/2/28 3:10:02

1. 前言

tcp套接字编程这里,我们将完成两份代码,一份是基于tcp实现普通的对话,另一份加上业务,client输入要执行的命令,server将执行结果返回给client

2. tcp_echo_server

udp类似,前两步:创建socket文件与bindIP和port到内核,不同的是socket函数第二个参数在tcp这里我们使用SOCK_STREAM,表示提供面向字节流、可靠的传输

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

udp中,接下来我们就可以让client与server通信了,但由于tcp是面向连接的,因此需要等待client连接,在连接之前,需要将sockfd设置为监听状态

#include <sys/types.h>
#include <sys/socket.h>

int listen(int sockfd, int backlog); # backlog 通常为4/8/16

服务器启动后,需要不断获取新连接

#include <sys/types.h>
#include <sys/socket.h>

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

accept返回一个文件描述符,与socket返回的文件描述符相比,两者的关系就像餐馆里的服务员与餐馆外的迎宾员,迎宾员通过各种说辞,将客人(也就是连接)引致餐馆交给服务员后转头又去迎接下一位客人,真正为客人提供服务的是餐馆里的服务员

这里的服务员就是accept返回的文件描述符,它才是真正的sockfd;迎宾员就是socket的返回值,也称为监听套接字(listensockfd)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

对两者加以区分后,我们也将原来的命名加以修改,且由于后续需要用到listensocfd,将它设置为成员变量

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

服务器启动,不断accept新连接,当获取一个连接失败时,进行获取下一个连接,好比迎宾员的邀请收到了你的冷落,它转头又去邀请下一位客人;当有连接到来时,交给sockfd,给连接提供服务

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在提供服务时,server首先读到来自client发送的信息,需要注意的时,tcp的读写使用recv/sendudp的读写使用recvfrom/sendto

#include <sys/types.h>
#include <sys/socket.h>

ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
# flags默认设为0

在这里,由于tcp是面向字节流的,读到的数据不一定是一个完整的报文,可能是半个,也可能是多个,需要我们进行处理,具体的细节在后面的文章中会详讲,这边就当作一个完整的数据

收到消息后,再给client回复;如果recv的返回值为0,表示client退出了,类似于管道:当读端读到0,表示写端关闭了

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在client方面,创建好socket文件之后,应该要bind自身IP和port,但上一篇文章说过,不需要显示bind;server在等待连接,client则需要去连接,当连接成功时,OS会自动bind好client的IP和port

#include <sys/types.h>
#include <sys/socket.h>

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

连接成功后,就能和server正常通信了

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当然,目前的代码缺点也很明显,它只能为一个client提供服务,由于client的服务是长服务,而我们只有一个进程,当第二个client来了,server在服务第一个进程,获取不上连接

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.1 多进程版本

当获取到新连接时,创建子进程,让子进程去提供服务,父进程等待;我们知道,父子进程之间独立,子进程会继承父进程的pcb,包括文件描述符表;子进程继承了父进程的listensockfdsockfd

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

父进程获取新连接拿到的sockfd,子进程会以写时拷贝的方式独有一份,此时父进程继续去获取连接,不会使用该sockfd,二我们知道文件描述符的个数是有上限的,父进程占着该文件描述符不用,可能会导致文件描述符泄漏的问题,因此,父进程要关闭sockfd

子进程只需要从父进程继承下来的sockfd即可,因此子进程最好关闭listensockfd

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

父进程在waitpid这里是阻塞等待,我们希望父进程继续去获取下一个连接,可以直接对SIGCHID进行忽略,这样子进程退出自动回收

这里使用的方法是,子进程再创建孙子进程,让后退出,父进程直接waitpid成功,继续获取下一个连接,孙子进程由于子进程先退,变成孤儿进程,被系统领养,释放的工作由系统完成

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.2 多线程版本

当主线程获取到新连接时,创建新线程,让新线程去执行服务

这里的问题是:

  1. 如何调用TcpServer中的Service函数
  2. 如何将sockfdaddr传给Service函数

我们建立一个内部类,存放TcpServer的指针和需要传递的变量,使用该类创建实例传给线程函数,在线程函数中调用

同时,为了不让主线程对新线程join而阻塞,将新线程分离

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意:这里不能使用上面一种方式创建实例,否则会因为释放两次ThreadData对象而导致client退出时server崩溃

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.3 线程池版本

利用之前的线程池,将Service函数作为任务交给线程池

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3. command_server

我们想实现当客户端发送一条指令给服务器时,服务器执行该指令,并将执行结果返回给客户端;服务器只负责读取数据,如何处理数据交给业务板块,也就是做到IO与业务解耦

我们知道,linux下的命令是创建子进程,由子进程执行,再将执行结果返回给bash,这里也类似,当服务器收到一条指令,需要创建子进程,由子进程处理

我们有现成的接口可以直接调用

#include <stdio.h>

FILE *popen(const char *command, const char *type);
# 父进程向管道读,type设为"r"

popen内部会创建管道和子进程,由子进程执行命令,再将执行结果写入管道,我们服务器就只需要向管道读取即可,返回值是一个封装的FILE*类型

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们还可以限制客户端能够执行的命令

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为什么要让服务器帮我们执行命令,我们直接在linux的命令行解释器下直接执行不就行了?实际上,在云服务器中,我们的指令不是在我们本主机上执行的,都是交给一个叫sshd的服务远程执行,再将执行结果返回的

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

因此,上面的代码能帮我们更好的了解云服务器的指令执行原理

4. 支持断线重连的客户端

有时因为网络问题导致与服务器的连接断开了,每次都要我们重新启动客户端太麻烦了,我们将客户端改成能够断线后重连,当重连一定次数还是无法连接服务器,此时才退出

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
[NetWork/Lesson2/2. command_server · baiyahua/Linux - 码云 - 开源中国](https://gitee.com/baiyahua/linux/tree/master/NetWork/Lesson2/2. command_server)

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

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

相关文章

NRBO-BiTCN时序预测 | Matlab基于NRBO-BiTCN牛顿拉夫逊算法优化双向时间卷积网络时间序列预测

NRBO-BiTCN时序预测 | Matlab基于NRBO-BiTCN牛顿拉夫逊算法优化双向时间卷积网络时间序列预测 目录 NRBO-BiTCN时序预测 | Matlab基于NRBO-BiTCN牛顿拉夫逊算法优化双向时间卷积网络时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab基于NRBO-BiTCN时序…

基于大数据爬+数据可视化的民族服饰数据分析系统设计和实现(源码+论文+部署讲解等)

博主介绍&#xff1a;CSDN毕设辅导第一人、全网粉丝50W,csdn特邀作者、博客专家、腾讯云社区合作讲师、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 技术范围…

Bean的注入、单例和多例

目录 注入Bean对象 属性注入 构造注入 属性注入专题 注入集合/数组 级联简单类型赋值 Bean的单例和多例 注入Bean对象 简单类型使用value(除Date)&#xff0c;非简单类型使用ref 属性注入 name规则&#xff1a;必须提供set方法&#xff0c;去掉set&#xff0c;第一个字…

【Ubuntu】清理、压缩VirtualBox磁盘空间大小

1、说明 本人为虚拟机创建了两个硬盘:root.vdi 和 hoom.vdi,在创建虚拟机时,分别挂载在/root目录和/home目录下。 下面演示分别清理、压缩两个磁盘的空间。 2、清理空间 1)清理 root.vid sudo dd if=/dev/zero of=/EMPTY bs=1M;sudo rm -f /EMPTY输出信息中会提示,如…

计算生成报价单小程序系统开发方案

计算生成报价单小程序报价系统&#xff0c;是根据商品品牌、类型、型号、规格、芯数、特性、颜色、分类进行选择不同的参数进行生成报价单&#xff0c;要求报价单支持生成图片、pdf、excel表格。 计算生成报价单小程序系统的主要功能模块有&#xff1a; 1、在线生成报价单&…

Git基础操作快速入门

Git是一个免费开源分布式版本控制工具&#xff0c;是由Linux的作者Linus开发的第二个伟大作品。2005年由于BitKeeper软件公司对Linux社区停止了免费使用权。Linus迫不得己自己开发了一个分布式版本控制工具&#xff0c;从而Git诞生了 目前使用Git作为版本控制的开源软件&#…

Android APP跳转到另一个APP

1. Android APP跳转到另一个APP 从当前APP去全新启动另外一个目标APP&#xff08;非覆盖同一个进程&#xff09; 1.1. 启动另外一个目标APP&#xff08;非覆盖原来APP的方式&#xff09; &#xff08;1&#xff09;当前APP加入获取权限声明&#xff1a;&#xff08;不加入权限…

云服务的flow流水线中项目配置与运行的错误解决

在阿里云的 **Flow** 流水线中&#xff0c;遇到 "codeup服务连接已失效" 错误通常是由于 **阿里云 Codeup**&#xff08;阿里云的 Git 仓库服务&#xff09;与流水线之间的连接中断导致的。这种问题一般可以通过以下几个步骤来解决&#xff1a; ### 1. **检查 Codeu…

PHP富文本编辑器eWebEditor实战指南

本文还有配套的精品资源&#xff0c;点击获取 简介&#xff1a;eWebEditor是一个基于PHP的开源在线文本编辑器&#xff0c;提供类似Word的用户界面&#xff0c;简化了网页文本的创建和编辑过程。它广泛适用于博客、论坛、CMS等平台的内容管理&#xff0c;具备富文本编辑、表格…

flink yarn模式3种提交任务方式

接上文&#xff1a;一文说清flink从编码到部署上线 1.引言 Apache Hadoop的Yarn是许多数据处理框架中非常流行的资源提供者。Flink的服务提交给Yarn的ResourceManager后&#xff0c;ResourceManager会在由Yarn的NodeManager管理的机器上动态分配运行容器。Flink在这些容器上部…

【JAVA高级篇教学】第三篇:Redisson作用简介

Redisson 是一个强大的 Redis 客户端&#xff0c;不仅可以实现限流和分布式锁&#xff0c;还提供了许多其他分布式工具和功能&#xff0c;涵盖数据结构、同步控制、消息队列等多个方面。以下是 Redisson 的主要作用和使用场景&#xff1a; 目录 1. 分布式数据结构 支持的数据…

springboot413福泰轴承股份有限公司进销存系统(论文+源码)_kaic

摘 要 使用旧方法对福泰轴承股份有限公司进销存系统的信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在福泰轴承股份有限公司进销存系统的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不…

Linux部署oceanbase

一、源码部署 1. 下载官网安装包 https://www.oceanbase.com/softwarecenter 2. 上传安装包并解压缩 #在/home目录下创建oceanbase文件夹 mkdir oceanbase cd oceanbase/ tar -xzf oceanbase-all-in-one-4.2.1_bp10_20241122.el7.x86_64.tar.gz 3. 安装 cd oceanbase-all-in…

分布式 分布式事务 总结

前言 相关系列 《分布式 & 目录》《分布式 & 分布式事务 & 总结》《分布式 & 分布式事务 & 问题》 分布式事务 所谓分布式事务是指操作范围笼罩多个不同节点的事务。例如对于订单节点&库存节点而言&#xff0c;一次完整的交易需要同时调动两个节…

【蓝桥杯每日一题】重新排序

重新排序 2024-12-8 蓝桥杯每日一题 重新排序 前缀和 差分 题目大意 给定一个数组 A 和一些查询 L i , R i Li_,R_i Li,​Ri​, 求数组中第 L i L_i Li​至第 R i R_i Ri​个元素之和。 小蓝觉得这个问题很无聊, 于是他想重新排列一下数组, 使得最终每个查 询结果的和尽可能…

jupyterlab 增加多个kernel,正确做法

1、背景 需要增加一个kernel然后相当于隔离一个环境 juypterlab Version 3.0.14 2、用conda 安装 例如&#xff0c;你在conda下有一个python 3.12 的环境 py312 ipython kernel install --user --namepy312 如果保持的话&#xff0c;用pip安装相应的包就好 3、检查是否配置好 …

uni-app 组成和跨端原理 【跨端开发系列】

&#x1f517; uniapp 跨端开发系列文章&#xff1a;&#x1f380;&#x1f380;&#x1f380; uni-app 组成和跨端原理 【跨端开发系列】 uni-app 各端差异注意事项 【跨端开发系列】uni-app 离线本地存储方案 【跨端开发系列】uni-app UI库、框架、组件选型指南 【跨端开…

KV Shifting Attention Enhances Language Modeling

基本信息 &#x1f4dd; 原文链接: https://arxiv.org/abs/2411.19574&#x1f465; 作者: Mingyu Xu, Wei Cheng, Bingning Wang, Weipeng Chen&#x1f3f7;️ 关键词: KV shifting attention, induction heads, language modeling&#x1f4da; 分类: 机器学习, 自然语言处…

算法-字符串-72.编辑距离

一、题目 二、思路解析 1.思路&#xff1a; 最少操作数——动态数组 res[i][j]:长度为i的字符串转化为长度为j字符串的最少操作 2.常用方法&#xff1a; 无 3.核心逻辑&#xff1a; 1.情况一&#xff1a;当word1为空&#xff0c;word2不为空时 for(int i0;i<size2;i){res[0…

云开发实战教程:手把手教你高效开发应用

声明&#xff1a;本文仅供实践教学使用&#xff0c;没有任何打广告成分 目录 1.引言 2.云开发 Copilot介绍 云开发 Copilot 的功能与特点 3.环境准备 步骤一登录账号 步骤二新建环境 4.开发实践 4.1AI 生成低代码应用 4.2AI 生成低代码页面/区块 4.3AI 优化低代码组件…