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

Linux --TCP协议实现简单的网络通信(中英翻译)

一、什么是TCP协议

1.1 、TCP是传输层的协议,TCP需要连接,TCP是一种可靠性传输协议,TCP是面向字节流的传输协议;

二、TCPserver端的搭建

2.1、我们最终好实现的效果是

客户端在任何时候都能连接到服务端,然后向服务端发送请求,服务端回应客户端的请求;且当客户端向服务端发送请求连接失败时(断网或者服务器故障),会有一个重新连接的状态,在某个时间段内可以不停尝试重新连接;在这里我们把请求和回应请求设计为一个英文翻译,即客户端发送英文,服务端翻译英文并把结果返回给客户端;

2.2 TCPserver第一步创建套接字
2.3、 准备数据

2.4、绑定

2.5、监听

以上初始化工作完成,接下来服务器运行: 

2.6、获取连接

2.7、让线程池取获取并处理任务

自己实现的简单版的线程池:

#pragma once
// 线程池类实现
#include <iostream>
#include <vector>
#include <queue>
#include <unistd.h>
const static int defaultNum = 5;
struct ThreadInfo
{pthread_t tid_;std::string threadname_;
};
template <class T>
class threadpool
{
public:void lock(){pthread_mutex_lock(&mutex_);}void unlock(){pthread_mutex_unlock(&mutex_);}void wakeup() // 唤醒{pthread_cond_signal(&cond_);}void sleep_t() // 休眠(到条件变量的等待队列里面等){pthread_cond_wait(&cond_, &mutex_);}bool isempty(){return task_queue.empty();}std::string getThreadname(pthread_t tid){for (auto &e : threads_){if (e.tid_ == tid)return e.threadname_;}return "None";}public:void push(const T &task){lock();task_queue.push(task);wakeup();unlock();}static void *HandlerTask(void *args) // 类内成员函数有this指针,会参数不匹配,加static修饰就没有了{threadpool<T> *tp = static_cast<threadpool<T> *>(args);std::string name=tp->getThreadname(pthread_self());while (true){tp->lock();// 1.获取任务while (tp->isempty()) // 防止伪唤醒{tp->sleep_t();}T t =tp->pop();tp->unlock();// 2.消费任务t();}}void start(){int threadcout = threads_.size();for (int i = 0; i < threadcout; i++){// 创建的同时把线程数组里的数据初始化好threads_[i].threadname_ = "thread-" + std::to_string(i + 1);pthread_create(&(threads_[i].tid_), nullptr, HandlerTask, this); // static成员函数不能访问成员变量,只能通过类对象访问}}T pop(){T out = task_queue.front();task_queue.pop();return out;}static threadpool<T> *GetInstacne() // 获取实例{                                   // 如果有多个线程同时进来获取实例呢?如果不上锁会导致对象被实例化多份出来if (tp_ == nullptr)             // 后面进来的大部分线程都会判断失败,不需要继续往获取锁{// 走到这里的只有一小部分线程pthread_mutex_lock(&lock_); // 上锁if (tp_ == nullptr)         // 只有第一次获取单例的线程需要进行条件判断,后续线程进来判断都失败{tp_ = new threadpool<T>();}pthread_mutex_unlock(&lock_); // 解锁}return tp_;}private:std::vector<ThreadInfo> threads_; // 存放线程信息(通过里面的tid找到线程)std::queue<T> task_queue;              // 存放任务的队列pthread_mutex_t mutex_;           // 访问队列的时候需要上锁pthread_cond_t cond_;             // 如果没有任务就去里面等threadpool(const T &) = delete;   // 把一切可构造出第二个对象的成员函数禁掉const threadpool<T> &operator=(const threadpool<T> &) = delete;threadpool(int threadnum = defaultNum): threads_(threadnum){// 初始化锁跟条件变量pthread_mutex_init(&mutex_, nullptr);pthread_cond_init(&cond_, nullptr);}~threadpool(){// 销毁锁和条件变量pthread_mutex_destroy(&mutex_);pthread_cond_destroy(&cond_);}static threadpool<T> *tp_;static pthread_mutex_t lock_;
};template <class T> // 静态类成员类外定义
threadpool<T> *threadpool<T>::tp_ = nullptr;template <class T>
pthread_mutex_t threadpool<T>::lock_ = PTHREAD_MUTEX_INITIALIZER; // 如果用全局锁需要对锁进行初始化跟销毁
2.8 把Task任务编写一下,即收发任务
#pragma once
#include <string>
#include"Init.hpp"
Init init;
const int buffersize = 1024;
class Task
{
private:int sock_fd;std::string clientip_;uint16_t clientport_;public:Task(const int &fd, const std::string &ip, const uint16_t &port): sock_fd(fd), clientip_(ip), clientport_(port){}void operator()(){Run();}void Run(){char buffer[buffersize];ssize_t n = read(sock_fd, buffer, sizeof(buffer));if (n > 0){buffer[n] = '\0';std::string message = buffer; // 获取client的信息std::string echo_message = init.translation(message);// 2.写// 把获取到的信息进行转换,输出client想要的信息ssize_t w = write(sock_fd, echo_message.c_str(), echo_message.size());if (w < 0){lg(WARNING, "Write fail!!");}else if (w == 0){lg(WARNING, "Read close!!");}}else if (n < 0){lg(INFO, "Read fail!! client ip is:%s, clien port is:%d",clientip_.c_str(),clientport_);}else{lg(WARNING, "Client close!! fd:%d, client ip: %s, client port: %d",sock_fd,clientip_.c_str(),clientport_);}close(sock_fd);}~Task(){}
};

 

2.9、server的main入口函数
#include "TcpServer.hpp"
#include <memory>
void Usage(std::string proc)
{std::cout<<"\n\rUsage:"<<proc<<" serverport[1024+]"<<std::endl;
}
//server serverport
int main(int argc,char * argv[])
{if(argc!=2){Usage(argv[0]);exit(1);}uint16_t port=std::stoi(argv[1]);lg.Enable(CLASSFILE);std::unique_ptr<TcpServer> ptr(new TcpServer(port));ptr->Init();ptr->Start();return 0;
}

三、客户端的编写

3.1
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#define SIZE 1024
void Usage(std::string proc)
{std::cout << "\n\rUsage:" << proc << " serverip serverport" << std::endl;
}
// client serverip serverport
int main(int argc, char *argv[])
{if (argc != 3){Usage(argv[0]);exit(1);}uint16_t serverport = std::stoi(argv[2]);std::string serverip = argv[1];// 2.准备数据struct sockaddr_in server;memset(&server, 0, sizeof(server)); // 初始化结构体server.sin_family = AF_INET;server.sin_port = htons(serverport);inet_pton(AF_INET, serverip.c_str(), &server.sin_addr);// 3.OS自动绑定在第一次连接成功时// 4.发起连接while (true){// 1.创建套接字int sock_fd = socket(AF_INET, SOCK_STREAM, 0);if (sock_fd < 0){return -1;}int cnt = 5;bool isconnect = false;do{ssize_t c = connect(sock_fd, (sockaddr *)&server, sizeof(server));if (c<0){cnt--;isconnect = true;std::cout << "Is connect!! time: " << cnt << std::endl;sleep(2);}else{break;}} while (cnt && isconnect);if (cnt == 0){std::cout << "user offline!!" << std::endl;break;}// 走到这里连接成功// 1.写std::cout << "Please enter@ " << std::endl;std::string line;std::getline(std::cin, line);ssize_t w = write(sock_fd, line.c_str(), line.size());if(w<0){std::cout<<"Write fail!!"<<std::endl;}// 2.读char buffer[SIZE];ssize_t r = read(sock_fd, buffer, sizeof(buffer));if (r > 0){buffer[r] = '\0';std::cout << buffer << std::endl;}close(sock_fd);}return 0;
}
3.2、在server中加入守护进程

         

守护进程的实现:

#pragma once
#include <unistd.h>
#include<cstdlib>
#include<signal.h>
#include<string>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>std:: string nullfile="/dev/null";
void Deamon(const std::string& cwd="")
{//1.忽略其他异常信号signal(SIGSTOP,SIG_IGN);signal(SIGPIPE,SIG_IGN);signal(SIGCLD,SIG_IGN);//2.自成会话if(fork()>0)exit(0);setsid();//3.更改调用进程的工作目录if(cwd.c_str()!=""){chdir(cwd.c_str());}//4.关闭标准输入输出错误流//打开垃圾桶int fd=open(nullfile.c_str(),O_RDONLY);//只读方式打开if(fd>0){//重定向到垃圾桶dup2(fd,0);dup2(fd,1);dup2(fd,2);}}
3.3、翻译服务的实现

        

#pragma oce
#include<unordered_map>
#include<fstream>
#include"log.hpp"
extern Log lg;
std::string filename="dict.txt";
std::string separator=":";
static bool split(const std::string&line,std::string*ptr1,std::string*ptr2)
{auto pos=line.find(separator);if(pos!=std::string::npos){*ptr1=line.substr(0,pos);*ptr2=line.substr(pos+1);return true;}return false;
}
class Init
{private:std::unordered_map<std::string,std::string> dict_;public:Init(){std::ifstream in(filename);if(!in.is_open()){lg(FATAL,"Ifstream open fail!!");exit(1);}std::string line;while(getline(in,line)){std::string ptr1,ptr2;split(line,&ptr1,&ptr2);dict_.insert({ptr1,ptr2});}in.close();}std::string translation(std::string&word){auto iter=dict_.find(word);if(iter!=dict_.end()){return iter->second;}return "Unknow";}~Init(){}
};

其中这个字典集随便找的一些内容:

3.4makefile 编译运行
.PHONY:all
all: tcpclient tcpserver
tcpclient:TcpClient.cppg++ -o $@ $^ -std=c++11
tcpserver:Main.cppg++ -o $@ $^ -std=c++11 -lpthread
.PHONY:clean
clean:rm -f tcpserver tcpclient

服务运行只要运行一次起来后有就会7*24小时在后台跑着:

相关文章:

Linux --TCP协议实现简单的网络通信(中英翻译)

一、什么是TCP协议 1.1 、TCP是传输层的协议&#xff0c;TCP需要连接&#xff0c;TCP是一种可靠性传输协议&#xff0c;TCP是面向字节流的传输协议&#xff1b; 二、TCPserver端的搭建 2.1、我们最终好实现的效果是 客户端在任何时候都能连接到服务端&#xff0c;然后向服务…...

LlamaIndex 工作流简介以及基础工作流

什么是工作流&#xff1f; 工作流是一种由事件驱动、基于步骤的应用程序执行流程控制方式。 你的应用程序被划分为多个称为“步骤&#xff08;Steps&#xff09;”的部分&#xff0c;这些步骤由“事件&#xff08;Events&#xff09;”触发&#xff0c;并且它们自身也会发出事…...

如何利用Elastic Stack(ELK)进行安全日志分析

在以下文章中&#xff0c;我将解释如何使用Elastic Stack&#xff08;ELK&#xff09;进行安全日志分析&#xff0c;以提高安全性和监控网络活动。ELK是一个功能强大的开源日志管理和分析平台&#xff0c;由Elasticsearch、Logstash和Kibana组成&#xff0c;适用于各种用例&…...

创客匠人:以 AI 利器赋能创始人 IP 打造,加速知识变现新路径

在知识付费与个人 IP 崛起的时代&#xff0c;创客匠人作为行业领先的技术服务商&#xff0c;正通过 AI 工具重构创始人 IP 打造与知识变现的生态。其推出的三大 AI 利器 ——AI 销售信、免训数字人、AI 智能客服&#xff0c;精准解决 IP 运营中的核心痛点。 以 AI 销售信为例&…...

Opencv中的copyto函数

一.OpenCV中copyto函数详解 copyto&#xff08;&#xff09;是 OpenCV 中用于图像复制和融合的核心函数&#xff0c;支持灵活的数据复制和掩模&#xff08;Mask&#xff09;操作&#xff0c;其功能和使用方法如下&#xff1a; 1. 核心功能 基础复制&#xff1a;将源图像&…...

TeamCity Agent 配置完整教程(配合 Docker Compose 快速部署)

在《使用 Docker Compose 从零部署 TeamCity PostgreSQL&#xff08;详细新手教程&#xff09;》中&#xff0c;我们成功部署了 TeamCity Server 和数据库服务。但要真正运行构建任务&#xff0c;还需要至少一个 Build Agent&#xff08;构建代理&#xff09;。 本教程将继续…...

基于深度强化学习的Scrapy-Redis分布式爬虫动态调度策略研究

在大数据时代&#xff0c;网络数据的采集与分析变得至关重要&#xff0c;分布式爬虫作为高效获取海量数据的工具&#xff0c;被广泛应用于各类场景。然而&#xff0c;传统的爬虫调度策略在面对复杂多变的网络环境和动态的抓取需求时&#xff0c;往往存在效率低下、资源浪费等问…...

在 Ubuntu 24.04 LTS 上安装 Jenkins 并配置全局工具(Git、JDK、Maven)

在 Ubuntu 24.04 LTS 上安装 Jenkins 并配置全局工具(Git、JDK、Maven) Jenkins 是一款开源的持续集成和持续交付(CI/CD)工具,在 DevOps 实践中有着广泛的应用。本文将手把手带你在 Ubuntu 24.04 LTS 系统中完成 Jenkins 的安装,并配置所需的全局工具:Git、JDK 和 Maven…...

Tika Server:企业级文档内容解析的轻量级服务化方案

目录 Tika Server&#xff1a;企业级文档内容解析的轻量级服务化方案 一、什么是 Tika Server&#xff1f; 二、Tika Server 的功能特点 1. 多种文档格式支持 2. 提取结构化信息 3. RESTful 接口设计 三、是否开源&#xff1f;是否支持私有化部署&#xff1f; 四、部署…...

LMG1020YFFR 电子元器件详解

LMG1020YFFR 电子元器件详解 基本概述 LMG1020YFFR是德州仪器(TI)生产的一款高性能、低侧栅极驱动器&#xff0c;属于其GaN(氮化镓)功率器件驱动产品系列。 主要功能特性 驱动能力&#xff1a; 峰值输出电流&#xff1a;5A/-5A 可驱动GaN FETs、SiC MOSFETs和高速硅MOSFETs…...

防爆型断链保护器的应用场景有哪些?

​ ​防爆型断链保护器是一种用于防止链条断裂导致设备损坏或安全事故的装置&#xff0c;尤其适用于存在爆炸风险的工业环境。以下是其主要应用场景&#xff1a; ​ ​1.石油化工行业 在石油化工厂、炼油厂等场所&#xff0c;防爆型断链保护器可用于保护输送设备&#xf…...

leetcode_206 反转链表

1. 题意 原地反转链表&#xff0c;非常经典的一道题。 2. 解决 2.1 非递归 非递归的比较好理解&#xff1b;链表需要维护前驱和后继两个信息&#xff0c;当我们要更改后继时&#xff0c;先要把原来的后继先存起来。 /*** Definition for singly-linked list.* struct List…...

OPenCV CUDA模块光流------高效地执行光流估计的类BroxOpticalFlow

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::cuda::BroxOpticalFlow 是 OpenCV CUDA 模块中实现Brox光流算法的类。该类用于在 GPU 上高效地计算两帧图像之间的稠密光流&#xff08;Dens…...

高考:如何合理选择学科、专业以及职业

如何合理选择学科、专业以及职业 一、自我认知&#xff1a;明确自身兴趣与优势&#xff08;一&#xff09;兴趣探索&#xff08;二&#xff09;能力评估&#xff08;三&#xff09;价值观与目标 二、外部调研&#xff1a;深入了解学科、专业与职业&#xff08;一&#xff09;学…...

K8S认证|CKS题库+答案| 3. 默认网络策略

目录 3. 默认网络策略 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、官网找模板 3&#xff09;、按照题目要求创建networkpolicy 4&#xff09;、应用networkpolicy 5&#xff09;、检查策略 3. 默认网络策略…...

HTTP、WebSocket、SSE 对比

特性HTTPWebSocketSSE (Server-Sent Events)通信模式请求-响应&#xff08;单向&#xff09;全双工双向通信服务器到客户端的单向通信连接方式短连接&#xff08;默认&#xff09;长连接长连接协议基础TCP&#xff08;HTTP/1.1, HTTP/2&#xff09;基于HTTP升级基于HTTP数据格式…...

Linux编程:1、文件编程

一、Linux 文件编程与 C 语言文件编程的区别 特性C 语言 I/O 库函数Linux 文件编程&#xff08;系统调用&#xff09;实现层面用户空间&#xff08;glibc 库&#xff09;内核空间&#xff08;系统调用&#xff09;跨平台性跨平台&#xff08;Windows/Linux&#xff09;仅限 Li…...

Kyosan K5BMC ELECTRONIC INTERLOCKING MANUAL 电子联锁

Kyosan K5BMC ELECTRONIC INTERLOCKING MANUAL 电子联锁...

【Spark征服之路-2.3-Spark运行架构】

运行架构 Spark 框架的核心是一个计算引擎&#xff0c;整体来说&#xff0c;它采用了标准 master-slave 的结构。 如下图所示&#xff0c;它展示了一个 Spark 执行时的基本结构。图形中的 Driver 表示 master&#xff0c;负责管理整个集群中的作业任务调度。图形中的 Executor …...

PART 6 树莓派小车+QT (TCP控制)

1. 树莓派作为服务器的程序 &#xff08;1&#xff09;服务器tcp_server_socket程序 可以实现小车前进、后退、左转、右转、加减速&#xff08;可能不行&#xff09; carMoveControl.py import RPi.GPIO as GPIO import time import tty,sys,select,termios import socket…...

软珊瑚成分 CI-A:靶向口腔癌细胞的 “氧化利剑” 与 ERK 密码

在生命科学探索的浩瀚星海中&#xff0c;癌症研究始终是最为耀眼却又充满挑战的领域之一。口腔癌&#xff0c;作为全球范围内日益严峻的公共健康问题&#xff0c;尤其在中南亚、美拉尼西亚以及我国台湾地区&#xff0c;其发病率和死亡率持续攀升&#xff0c;如同隐藏在黑暗中的…...

Cilium动手实验室: 精通之旅---4.Cilium Gateway API - Lab

Cilium动手实验室: 精通之旅---4.Cilium Gateway API - Lab 1. 环境准备2. API 网关--HTTP2.1 部署应用2.2 部署网关2.3 HTTP路径匹配2.4 HTTP头匹配 3. API网关--HTTPS3.1 创建TLS证书和私钥3.2 部署HTTPS网关3.3 HTTPS请求测试 4. API网关--TLS 路由4.1 部署应用4.2 部署网关…...

【芯片设计- RTL 数字逻辑设计入门 4.2 -- 组合逻辑赋值 + 时序逻辑状态保持】

文章目录 Overview原语句分析变量含义假设(根据命名推测)状态更新逻辑详解状态转移逻辑举个实际例子小结Overview 本文将详细介绍 verilog rtl 中 assign reg_halt_mode_nx = halt_taken | (reg_halt_mode & ~halt_return);的作用,以及这里为何要使用 reg_halt_mode,…...

如何使用索引和条件批量更改Series数据

视频演示 如何通过索引与布尔条件修改 pandas Series&#xff1f;实操演示来了 一、前言&#xff1a;掌握Series数据修改是数据处理的基础 在使用Python进行数据分析时&#xff0c;Pandas库的Series对象是最常用的结构之一。在上一个视频中我们已经学习了如何创建Series对象&a…...

Java转Go日记(六十):gin其他常用知识

1. 日志文件 package mainimport ("io""os""github.com/gin-gonic/gin" )func main() {gin.DisableConsoleColor()// Logging to a file.f, _ : os.Create("gin.log")gin.DefaultWriter io.MultiWriter(f)// 如果需要同时将日志写入…...

89.实现添加收藏的功能的后端实现

实现完查看收藏列表之后&#xff0c;实现的是添加收藏的功能 我的设想是&#xff1a;在对话界面中&#xff0c;如果用户认为AI的回答非常好&#xff0c;可以通过点击该回答对应的气泡中的图标&#xff0c;对该内容进行添加 所以后端实现为&#xff1a; service类中添加&…...

v1.0.1版本更新·2025年5月22日发布-优雅草星云物联网AI智控系统

v1.0.1版本更新2025年5月22日发布-优雅草星云物联网AI智控系统 开源地址 星云智控官网&#xff1a; 优雅草星云物联网AI智控软件-移动端vue: 优雅草星云物联网AI智控软件-移动端vue 星云智控PC端开源&#xff1a; 优雅草星云物联网AI智控软件-PC端vue: 优雅草星云物联网AI…...

如何创造出一种不同于程序语言的人与机器自然交互语言?

人机交互自然语言通过模拟人类日常交流方式&#xff0c;使机器能够理解并响应人类的自然表达&#xff0c;从而打破编程语言的复杂性壁垒&#xff0c;极大地提升人机协同的效率和自然性&#xff0c;让机器更好地融入人类的工作与生活场景。创造一种通用的人与机器自然交互语言是…...

宝塔think PHP8 安装使用FFmpeg 视频上传

宝塔think PHP8 安装使用FFmpeg 一、 安装think PHP8二、安装 FFmpeg1&#xff0c;登录到宝塔面板。2&#xff0c;进入“软件商店”。3&#xff0c;搜索“FFmpeg”。4&#xff0c;选择版本点击安装。5&#xff0c;检查 FFmpeg 是否安装成功6&#xff0c; 在 ThinkPHP 8 中使用 …...

26.【新型数据架构】-零ETL架构

26.【新型数据架构】-零ETL架构:减少数据移动,原系统直接分析;典型实现(AWS Zero-ETL) 一、零ETL的本质:从“数据搬运工”到“数据翻译官” 传统ETL(Extract-Transform-Load)需要将数据从源系统抽取、清洗、转换后加载到目标系统,这一过程往往耗时费力,且面临数据延…...