当前位置: 首页 > news >正文

【Linux网络】TCP_Socket

目录

TCP协议(传输控制协议)

listen状态

accept和connect

TCP_echo_server

(1)创建套接字

(2)绑定

(3)设置listen状态

(4)loop

(5)客户端

多线程远程执行命令


TCP协议(传输控制协议)

传输层协议
有连接
可靠传输(前提网络要联通,复杂,维护性要更强)
面向字节流

tcp和udp在创建套接字和绑定部分是一样的;

不同的是,tcp在服务端绑定后需要将套接字的状态设置为listen状态,除此之外,在通信前要获取新连接;在客户端也要connect;

因为tcp是面向连接的,tcp需要未来不断地能够做到获取连接;

listen状态

accept和connect


  

 


 在TCP(传输控制协议)的服务端中获取新连接是至关重要的,原因如下:

  •  建立连接

TCP是面向连接的协议。客户端发起连接请求(通过 connect 函数),服务端需要接受这些请求(通过 accept 函数)来建立连接。这个连接是双向的通信链路,允许数据在客户端和服务端之间可靠地传输。例如,当你访问一个网站时,你的浏览器(客户端)向Web服务器(服务端)发起TCP连接请求,服务器接受这个请求后,两者之间就建立了一条可靠的通信链路,用于传输网页数据。

  •  并发处理

服务端通常需要同时处理多个客户端的请求。通过获取新连接,服务端可以为每个客户端创建一个独立的连接,从而实现并发处理。例如,一个在线游戏服务器可能需要同时处理成千上万的玩家连接。每个玩家的客户端都会向服务器发起TCP连接请求,服务器接受这些请求并创建对应的连接,这样就能同时为多个玩家提供服务。

  • 数据交互

获取新连接是数据传输的起点。一旦连接建立,客户端和服务端就可以通过读写套接字( read 和 write 函数,或者 recv 和 send 函数)来交换数据。例如,在一个文件传输服务中,客户端请求下载文件,服务端接受连接后,就可以通过已建立的连接将文件数据发送给客户端。
 

TCP_echo_server

下面我们来手动实现一下tcp_echo_server;按照下面的流程来实现:

(1)创建套接字

// 1、创建套接字
_listensockfd = ::socket(AF_INET, SOCK_STREAM, 0);
if (_listensockfd < 0)
{LOG(FATAL, "socket error\n");exit(SOCKET_ERROR);
}
LOG(DEBUG, "socket create sucess\n");

(2)绑定

struct sockaddr_in local;
memset(&local, 0, sizeof(local));
local.sin_family = AF_INET;
local.sin_port = htons(_port);
local.sin_addr.s_addr = INADDR_ANY;int n = ::bind(_listensockfd, (struct sockaddr *)&local, sizeof(local));

(3)设置listen状态

// 3、设置套接字为listen状态
// 因为tcp是面向连接的,tcp需要未来不断地能够做到获取连接
int m = listen(_listensockfd, MAXCOUNT);
if (m < 0)
{LOG(FATAL, "listen error\n");
}
LOG(INFO, "listen sucess\n");

(4)loop

(1)获取新连接

// 获取新连接
struct sockaddr_in client;
socklen_t len = sizeof(client);
int sockfd = ::accept(_listensockfd, (struct sockaddr *)&client, &len);
if (sockfd < 0)
{LOG(WARNING, "accept error\n");continue;
}
InetAddr addr(client);
LOG(INFO, "get a new link,client info :%s\n", addr.Addrstr().c_str());

(2)

因为下面的几个版本都需要用的Service函数,我先提前放到这里;

    void Service(int sockfd, InetAddr addr){while (true){char inbuffer[2048];ssize_t n = ::read(sockfd, inbuffer, sizeof(inbuffer) - 1); // 读消息,-1是因为它是系统调用不会做字符串处理if (n > 0){inbuffer[n] = 0;string echo_string = "[server echo]# ";echo_string += inbuffer;n = ::write(sockfd, echo_string.c_str(), echo_string.size()); // 写消息}else if (n == 0) // 读到文件结尾,也就是通信结束{LOG(INFO, "client %s quit\n", addr.Addrstr().c_str());break;}else{LOG(ERROR, "read server error:%s\n", addr.Addrstr().c_str());break;}}}

1、version 0 版本

Service(sockfd, addr);

2、version 1 ----多进程版本

 pid_t id =fork();
if(id==0)
{
::close(_listensockfd);
if(fork()>0)exit(0);//子进程退出
Service(sockfd, addr);//孙进程会造成僵尸进程
exit(0);
}
//father
::close(sockfd);
int n=waitpid(id,nullptr,0);//1、忽略;2、父子孙
if(n>0)
{
LOG(INFO,"wait child sucess\n");
}

3、version 2 ----多线程版本

pthread_t tid;
ThreadDate *td = new ThreadDate(sockfd, this, addr);
pthread_create(&tid, nullptr, Execute, td); // 新线程分离

4、version 3 ---线程池版本

task_t aa=std::bind(&TcpServer::Service,this,sockfd,addr);
ThreadPool<task_t>::GetInstance()->Equeue(aa);

(5)客户端

以上我们就完成了tcp_echo_server,也就是用tcp实现的一个简单的通信;

多线程远程执行命令

这里我们用version 2 多线程版本来实现远程执行命令;

为了使代码更加美观,我们在version2版本的基础上,将Service函数进行封装;将它封装到command.hpp的HandlerCommand函数里面;

这样我们调用回调函数,然后再主函数中进行绑定即可;

using command_server_t =std::function<void(int sockfd, InetAddr addr)>;
void HandlerCommand(int sockfd, InetAddr addr)
{while (true){char inbuffer[2048];ssize_t n = ::recv(sockfd, inbuffer, sizeof(inbuffer) - 1,0); // 读消息,-1是因为它是系统调用不会做字符串处理             if (n > 0){inbuffer[n] = 0;string result = Excute(inbuffer);n = ::send(sockfd, result.c_str(), result.size(),0); // 写消息}else if (n == 0) // 读到文件结尾,也就是通信结束{LOG(INFO, "client %s quit\n", addr.Addrstr().c_str());break;}else{LOG(ERROR, "read server error:%s\n", addr.Addrstr().c_str());break;}}
}

完成上面的准备工作,怎么执行命令?

在之前我写过手写shell的文章,可以直接用里面的代码,文章用的是exec*函数来执行命令;但是这里我们用一个更加简单的函数:popen直接执行即可;

string Excute(const string &cmdstr)
{FILE *fp=popen(cmdstr.c_str(),"r");string result;if(fp){char line[1024];while(fgets(line,sizeof(line),fp))//读文件{result+=line;}return result;}else{return "execute error";}
}

完整代码:

tcp_echo_server:

登录 - Gitee.com

远程执行命令:

登录 - Gitee.com

相关文章:

【Linux网络】TCP_Socket

目录 TCP协议&#xff08;传输控制协议&#xff09; listen状态 accept和connect TCP_echo_server (1)创建套接字 &#xff08;2&#xff09;绑定 &#xff08;3&#xff09;设置listen状态 &#xff08;4&#xff09;loop &#xff08;5&#xff09;客户端 多线程远程…...

NVR批量管理软件/平台EasyNVR多个NVR同时管理支持视频投放在电视墙上

在当今智能化、数字化的时代&#xff0c;视频监控已经成为各行各业不可或缺的一部分&#xff0c;无论是公共安全、交通管理、企业监控还是智慧城市建设&#xff0c;都离不开高效、稳定的视频监控系统的支持。而在这些应用场景中&#xff0c;将监控视频实时投放到大屏幕电视墙上…...

Springboot集成阿里云通义千问(灵积模型)

我这里集成后&#xff0c;做成了一个工具jar包&#xff0c;如果有不同方式的&#xff0c;欢迎大家讨论&#xff0c;共同进步。 集成限制&#xff1a; 1、灵积模型有QPM(QPS)限制&#xff0c;每个模型不一样&#xff0c;需要根据每个模型适配 集成开发思路&#xff1a; 因有…...

微信公众号(或微信浏览器)获取openId(网页授权)

下单支付需要openId 首先授权去拿到code --然后调用后太换取openId 1.去拿取code 下图中执行到window.location.href &#xff08; redirect_uri 传入当前路径-&#xff09;–执行后重新跳转到当前页面–但是路径上会带上code参数 //然后调用后台方法–将code传给后台得到 o…...

C++算法第五天

本篇文章继续和大家一起刷算法题 第一题 题目链接 . - 力扣&#xff08;LeetCode&#xff09; 题目解析 题目要求&#xff1a; 这是一个连续的子数组 计算子数组内元素的和&#xff0c;若数组内元素的和符合 > target的值并且该子数组的长度是最短的&#xff0c;则返回…...

牛客网剑指Offer-树篇-JZ26 树的子结构

题目 来源&#xff1a;JZ26 树的子结构 描述 输入两棵二叉树A&#xff0c;B&#xff0c;判断B是不是A的子结构。&#xff08;我们约定空树不是任意一个树的子结构&#xff09; 假如给定A为{8,8,7,9,2,#,#,#,#,4,7}&#xff0c;B为{8,9,2}&#xff0c;2个树的结构如下&#xff…...

FFmpeg 4.3 音视频-多路H265监控录放C++开发六,使用SDLVSQT显示yuv文件

使用QT 显示YUV 文件 在最后一帧的时候会不停的显示最后一帧图片。 Vsqtshowyuv.h #pragma once#include <QtWidgets/QWidget> #include "ui_vsqtshowyuv.h" #include <sdl/SDL.h> #include <iostream> #include <fstream> #include <Q…...

Spring 设计模式之适配器模式

Spring 设计模式之适配器模式 适配器模式用到的场景java举例 适配器模式 适配器模式&#xff08;Adapter Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许接口不兼容的类一起工作。 其核心思想是通过一个适配器类将不兼容的接口转换成客户端期望的另一个接口&…...

多传感器数字化分析系统

在工业飞速发展的今天&#xff0c;设备的安全稳定运行成为企业高效生产的关键因素。然而&#xff0c;传统的人工巡检方式面临着诸多挑战&#xff0c;如效率低下、漏检误检以及难以精准掌握设备运行状态等。旗晟凭借深厚的技术积累和创新精神&#xff0c;推出了多传感器数字化分…...

Java 基础教学:面向对象编程基础-封装、继承与多态

面向对象编程&#xff08;OOP&#xff09;是现代编程的重要范式&#xff0c;Java 语言提供了丰富的 OOP 特性&#xff0c;主要包括封装、继承和多态。本文将详细讲解这三个概念及其实现方式&#xff0c;并提供相应的代码示例。 1. 封装 1.1 概念 封装是将对象的状态&#xf…...

Ubuntu环境本地部署DbGate数据库管理工具并实现无公网IP远程访问

文章目录 前言1. 安装Docker2. 使用Docker拉取DbGate镜像3. 创建并启动DbGate容器4. 本地连接测试5. 公网远程访问本地DbGate容器5.1 内网穿透工具安装5.2 创建远程连接公网地址5.3 使用固定公网地址远程访问 前言 本文主要介绍如何在Linux Ubuntu系统中使用Docker部署DbGate数…...

【AI抠图整合包及教程】Meta SAM 2:视觉分割的革命性飞跃

在人工智能的浪潮中&#xff0c;每一次技术的革新都如同一场视觉盛宴&#xff0c;让我们见证着数字时代的变迁。Meta再次以Segment Anything Model 2&#xff08;SAM 2&#xff09;引领了图像和视频分割技术的新纪元。作为首个用于实时、可提示的图像和视频对象分割的统一模型&…...

使用语言模型进行文本摘要的五个级别(llm)

视频链接&#xff1a;5 Levels Of LLM Summarizing: Novice to Expert...

ubuntu交叉编译libffi库给arm平台使用

1.下载并解压&#xff1a; 2.生成makefile 编译&#xff1a; make 编译成功&#xff1a; 安装&#xff1a; make install 安装成功 查看安装后的libffi库...

【jvm】空间分配担保策略

目录 1. 说明2. 工作原理2.1 估算新生代存活对象大小2.2 判断老年代的剩余空间2.3 触发Full GC的条件 3. 相关参数与配置3.1 -XX:HandlePromotionFailure3.2 -XX:PretenureSizeThreshold3.3 -XX:MaxTenuringThreshold3.4 -XX:TargetSurvivorRatio 4.作用与意义 1. 说明 1.在Ja…...

iQOO手机怎样将屏幕投射到MacBook?可以同步音频吗?

众所周知&#xff0c;苹果品牌的设备自己有AirPlay的投屏功能&#xff0c;iPhone要投屏到MacBook只要连接同一网络&#xff0c;然后开启AirPlay就可以投屏。但其他品牌的手机没有AirPlay&#xff0c;怎么将手机屏幕投射到MacBook呢&#xff1f; 安卓系统的手机可以使用无线投屏…...

BUU usualCrypt1

查壳&#xff0c;32bit&#xff0c;丢进ida32中进行反编译&#xff0c;简单的不多说&#xff0c;直接进main分析 简单分析&#xff0c;打上注释&#xff0c;没啥好看的&#xff0c;就一个加密函数&#xff0c;加密完后和一个字符串进行比较&#xff0c;由此可以逆推出加密前的字…...

第十七章 标准库特殊设施

17.1 tuple类型 当希望将一些数据合成单一对象&#xff0c;但又不想麻烦地定义一个新数据结构来表示这些数据时&#xff0c;tuple非常有用。tuple是类似pair的模板。 tuple<size_t, size_t, size_t> threeD; //三个成员都设置为0//为每个成员提供初始值 tuple<strin…...

【格言分享】程序员的经典名言解读

上一期文章我们分享了一些程序员的经典名言,每一句都蕴含着深刻的道理。 接下来就给大家一个一个分析一下 这些格言确实捕捉到了编程和软件开发的精髓,每一条都蕴含着丰富的经验和智慧。下面我将逐一解释这些格言,并分享一些我的看法。 C程序员永远不会灭亡。他们只是cast…...

SpringBoot接收LocalDateTime参数

一、通过RequestBody接收 方式1&#xff1a;实体类上加上 JsonFormat&#xff0c;并通过 pattern 属性指定时间格式 public class Time {JsonFormat(pattern "yyyy-MM-dd HH:mm:ss")LocalDateTime localDateTime;JsonFormat(pattern "yyyy-MM-dd")Loca…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?

uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件&#xff0c;用于在原生应用中加载 HTML 页面&#xff1a; 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

初探Service服务发现机制

1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能&#xff1a;服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源&#xf…...

人机融合智能 | “人智交互”跨学科新领域

本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...

Docker拉取MySQL后数据库连接失败的解决方案

在使用Docker部署MySQL时&#xff0c;拉取并启动容器后&#xff0c;有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致&#xff0c;包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因&#xff0c;并提供解决方案。 一、确认MySQL容器的运行状态 …...

前端开发者常用网站

Can I use网站&#xff1a;一个查询网页技术兼容性的网站 一个查询网页技术兼容性的网站Can I use&#xff1a;Can I use... Support tables for HTML5, CSS3, etc (查询浏览器对HTML5的支持情况) 权威网站&#xff1a;MDN JavaScript权威网站&#xff1a;JavaScript | MDN...

21-Oracle 23 ai-Automatic SQL Plan Management(SPM)

小伙伴们&#xff0c;有没有迁移数据库完毕后或是突然某一天在同一个实例上同样的SQL&#xff0c; 性能不一样了、业务反馈卡顿、业务超时等各种匪夷所思的现状。 于是SPM定位开始&#xff0c;OCM考试中SPM必考。 其他的AWR、ASH、SQLHC、SQLT、SQL profile等换作下一个话题…...

C/Python/Go示例 | Socket Programing与RPC

Socket Programming介绍 Computer networking这个领域围绕着两台电脑或者同一台电脑内的不同进程之间的数据传输和信息交流&#xff0c;会涉及到许多有意思的话题&#xff0c;诸如怎么确保对方能收到信息&#xff0c;怎么应对数据丢失、被污染或者顺序混乱&#xff0c;怎么提高…...