Socket编程-tcp

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.mzph.cn/news/888696.shtml

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

相关文章

深入浅出云计算 ---笔记

这是博主工作闲时的一些日常学习记录&#xff0c;有些之前很熟悉的&#xff0c;但工作中不常用&#xff0c;慢慢就遗忘了&#xff0c;在这里记录&#xff0c;也是为了激励自己坚持复习&#xff0c;如果有能帮到你&#xff0c;那我将感到非常的荣幸~ 快速到达↓↓↓ IaaS篇>&…

14 设计模式值观察者模式(书籍发布通知案例)

一、观察者模式定义 在日常开发中&#xff0c;我们经常会遇到一种场景&#xff1a;某个对象的状态发生变化时&#xff0c;需要通知并更新其他相关对象。这时&#xff0c;观察者模式便成为了解决问题的有效方案。观察者模式是一种常见的设计模式&#xff0c;它允许一个对象的状态…

15分钟训练数字人MimicTalk

只需15分钟&#xff0c;就能训练高质量&#xff0c;个性化数字人大模型。由浙江大学与字节跳动联合推出MimicTalk算法&#xff0c;目前已开源。 在外表和说话风格上和真人相似。将通用3D数字人大模型适应到单个目标人&#xff0c;采用动静结合的高效微调方案&#xff0…

c++高级篇(四) ——Linux下IO多路复用之epoll模型

IO多路复用 —— epoll 前言 在之前我们就已经介绍过了select和poll,在作为io多路复用的最后一个的epoll,我们来总结一下它们之间的区别: a select 实现原理 select 通过一个文件描述符集合&#xff08;fd_set&#xff09;来工作&#xff0c;该集合可以包含需要监控的文件…

【kettle】mysql数据抽取至kafka/消费kafka数据存入mysql

目录 一、mysql数据抽取至kafka1、表输入2、json output3、kafka producer4、启动转换&#xff0c;查看是否可以消费 二、消费kafka数据存入mysql1、Kafka consumer2、Get records from stream3、字段选择4、JSON input5、表输出 一、mysql数据抽取至kafka 1、表输入 点击新建…

docker-compose部署skywalking 8.1.0

一、下载镜像 #注意 skywalking-oap-server和skywalking java agent版本强关联&#xff0c;版本需要保持一致性 docker pull elasticsearch:7.9.0 docker pull apache/skywalking-oap-server:8.1.0-es7 docker pull apache/skywalking-ui:8.1.0二、部署文件docker-compose.yam…

用Python开发一个经典贪吃蛇小游戏

Python 是开发小游戏的绝佳工具,借助第三方库,如 pygame,我们可以快速开发一个经典的贪吃蛇游戏。本篇将介绍如何用 Python 实现一个完整的贪吃蛇小游戏。 一、游戏设计 1.1 游戏规则 玩家通过方向键控制贪吃蛇移动。贪吃蛇吃到食物后会变长,同时得分增加。如果贪吃蛇撞到…

在 MacOS 上为 LM Studio 更换镜像源

在 MacOS 之中使用 LM Studio 部署本地 LLM时&#xff0c;用户可能会遇到无法下载模型的问题。 一般的解决方法是在 huggingface.co 或者国内的镜像站 hf-mirror.com 的项目介绍卡页面下载模型后拖入 LM Studio 的模型文件夹。这样无法利用 LM Studio 本身的搜索功能。 本文将…

vue中.sync修饰符的用法

一、什么是.sync修饰符 在Vue.js中&#xff0c;.sync 修饰符用于创建一个双向绑定的 prop。它使子组件能够更新父组件的 prop 值&#xff0c;实现父子组件之间的双向数据同步。具体来说&#xff0c;.sync 修饰符主要有以下几个功能&#xff1a; 简化双向绑定&#xff1a; 使用…

【附源码】基于环信鸿蒙IM SDK实现一个聊天Demo

项目背景 本项目基于环信IM 鸿蒙SDK 打造的鸿蒙IM Demo&#xff0c;完全适配HarmonyOS NEXT系统&#xff0c;实现了发送消息&#xff0c;添加好友等基础功能。代码开源&#xff0c;功能简洁&#xff0c;如果您有类似开发需求可以参考。 源码地址&#xff1a;https://github.c…

SHELL----正则表达式

一、文本搜索工具——grep grep -参数 条件 文件名 其中参数有以下&#xff1a; -i 忽略大小写 -c 统计匹配的行数 -v 取反&#xff0c;不显示匹配的行 -w 匹配单词 -E 等价于 egrep &#xff0c;即启用扩展正则表达式 -n 显示行号 -rl 将指定目录内的文件打…

Can‘t find variable: token(token is not defined)

文章目录 例子 1&#xff1a;使用 var例子 2&#xff1a;使用 let 或 const例子 3&#xff1a;异步操作你的代码中的情况 Cant find variable: tokentoken is not defined源代码 // index.jsPage({data: {products:[],cardLayout: grid, // 默认卡片布局为网格模式isGrid: tr…

Kafka-创建topic源码

一、命令创建topic kafka-topics --create --topic quickstart-events --bootstrap-server cdh1:9092 --partitions 2 --replication-factor 2 二、kafka-topics脚本 exec $(dirname $0)/kafka-run-class.sh org.apache.kafka.tools.TopicCommand "$" 脚本中指定了…

【AI系统】GhostNet 系列

GhostNet 系列 本文主要会介绍 GhostNet 系列网络&#xff0c;在本文中会给大家带来卷积结构的改进方面的轻量化&#xff0c;以及与注意力(self-attention)模块的进行结合&#xff0c;部署更高效&#xff0c;更适合移动计算的 GhostNetV2。让读者更清楚的区别 V2 与 V1 之间的…

传奇996_51——脱下装备,附加属性设为0

奶奶的lua怎么都修改不了&#xff0c;可以调用txt的 ; LINKPICKUPITEM ; ChangeitemaddvaLue -1 5 0 ; GETITEMADDVALUE 3 5 M10 ; SENDUPGRADEITEM ; SENDMSG 9 你的衣服附加了<$STR(M10)>点防御属性. 或者lua callscriptex(actor,“LINKPICKUPITEM”) callscriptex(…

YOLOv8改进,YOLOv8引入CARAFE轻量级通用上采样算子,助力模型涨点

摘要 CARAFE模块的设计目的是在不增加计算复杂度的情况下,提升特征图的质量,特别是在视频超分辨率任务中,提升图像质量和细节。CARAFE结合了上下文感知机制和聚合特征的能力,通过动态的上下文注意力机制来提升细节恢复的效果。 理论介绍 传统的卷积操作通常依赖于局部区域…

大型制造企业IT蓝图、信息化系统技术架构规划与实施路线方案

关注 获取ppt​​​​​​全文&#xff0c;请关注作者

HTTP 长连接(HTTP Persistent Connection)简介

HTTP长连接怎么看&#xff1f; HTTP 长连接&#xff08;HTTP Persistent Connection&#xff09;简介 HTTP 长连接&#xff08;Persistent Connection&#xff09;是 HTTP/1.1 的一个重要特性&#xff0c;它允许在一个 TCP 连接上发送多个 HTTP 请求和响应&#xff0c;而无需为…

MySQL悲观锁和乐观锁

MySQL悲观锁和乐观锁 在数据库中&#xff0c;锁是用来管理并发控制的一种机制&#xff0c;确保数据的一致性和完整性。MySQL中的悲观锁和乐观锁是两种不同的并发控制策略&#xff0c;它们在处理并发事务时采用不同的方法。 悲观锁&#xff08;Pessimistic Locking&#xff09…

控制模组进入飞行模式

控制模组进入飞行模式 控制模组进入飞行模式 控制模组进入飞行模式 控制模组进入飞行模式 #!/bin/bash ## 5G模组采用USB3.0与上位机连接&#xff0c;usb接口在上位机上虚拟出多个port,其中一个可用于发送AT命令&#xff0c;控制模组 ## 本脚本控制模组进入飞行模式## flyin …