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

Tcp_socket

 Tcp不保证报文完整性(面向字节流)

所以我们需要在应用层指定协议,确保报文完整性

// {json} -> len\r\n{json}\r\n
bool Encode(std::string &message)
{if(message.size() == 0) return false;std::string package = std::to_string(message.size()) + Sep + message + Sep;message = package;return true;
}

OSI与TCP/IP

为什么tcp四层协议,IOS七层协议?

虽然IOS七层协议很完善,但实际实现时,有些层次被合并。

将IOS与实际情况相结合
tcp中,把上三层归为 应用层
最后二层归为  网卡 层

OSI七层协议
​​​​​​
TCP四层模型对应OSI
TCP/IP四层模型与OSI对应关系

Tcp与Udp区别

tcp需要握手后建立连接才可以开始服务
使用listen握手

[listen]声明:

       int listen(int sockfd, int backlog);

[accept]声明:

SYNOPSIS#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

[connect声明]

SYNOPSIS#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);


listen返回的fd是给accept使用的,不可用来I/O
我们应对accept 返回的fd进行I/O

Tcp的 accept 返回的fd更像是文件,可以用read读取,因为Tcp是面向字节流
Udp的recvfrom返回的fd不可read等操作,因为Udp不是面向字节流

和Udp一样,Tcp也是全双工通信的(可同时读写)

telnet [域名] 端口号

远程登陆

struct sockaddr

struct sockaddr   基类
struct sockaddr_in,inet,网络间通信
struct sockaddr_un,unix,本机通信
这三个struct前2字节都是16位地址类型(C语言实现多态)


与Tcp协议server交流时,client应先connect,connect成功后才可以write/read
到client与server段开链接时,server中的read会立即返回0,表示与client失去连接

fd & 多进程

子进程继承父进程的文件描述符表。两张,父子各一张(可以理解为子进程浅拷贝父进程fd表,表中fd指向与父进程相同)

父子进程共享的fd中,如果其中一个进程关闭fd,另一个进程中对应fd不受影响,因为fd指向文件具有引用计数,只有引用数为0时,fd指向文件才会真正关闭

将子进程与父进程脱离的方法
signal(SIGCHLD,SIG_IGN),会使系统自动回收子进程
在子进程中生成孙子进程,之后关闭子进程,孙子进程就变为孤儿进程,由系统自动回收。

和进程不同,父子线程共享一张fd表,所以子线程中不用也不能关闭fd。

recv /send  与 read/write

使用recv & send 代替read & write
后者可能导致数据不完整,所以建议前者

[recv]

       #include <sys/types.h>#include <sys/socket.h>ssize_t recv(int sockfd, void *buf, size_t len, int flags);

[send]

 #include <sys/types.h>#include <sys/socket.h>ssize_t send(int sockfd, const void *buf, size_t len, int flags);


tips:

fd是有用的有限的资源,fd周期随进程。如果不关闭fd,会造成fd泄漏

类静态函数成员

类的静态成员函数不能直接访问类的实例成员(非静态成员),但可以访问类的静态成员。
这是因为静态成员函数与类的实力无关(可能使用静态成员函数时,类还没有实例化)

非静态成员函数可以访问静态成员函数(因为后者实例化一定比前者早)


server类中调用pthread_thread_creat时其函数参数的对应函数(void*(void*))不能接收类内普通自定义参数(因为其只能传递server的this),
只能使server类的静态函数成员作为pthread_thread_creat的函数参数。
通过想类的静态函数成员传递包含有线程所需data+server的this指针,在静态成员函数中通过this调用server类的普通成员函数(同时传递data),实现传参。

popen & pclose

封装了pipe 与 fork  /  exec

#include <stdio.h>FILE *popen(const char *command, const char *type);int pclose(FILE *stream);

板书笔记

TcpEchoShell_code

code/lesson35/1. EchoServer · whb-helloworld/112 - 码云 - 开源中国

 TcpServer.cc

#include "TcpServer.hpp"
#include "CommandExec.hpp"
#include <functional>
#include <memory>using task_t = function<std::string (std::string)>;
// using namespace 
int main()
{ENABLE_CONSOLE_LOG();Command cmd;task_t task = [&cmd](std::string cmdstr){return cmd.Execute(cmdstr);};std::unique_ptr<TcpServer> tsvr = std::make_unique<TcpServer>(task);tsvr->InitServer();tsvr->Start();return 0;
}

TcpServer.hpp

#pragma once#include <iostream>
#include <cstring>
#include <string>
#include <cerrno>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <pthread.h>
#include <functional>#include "Log.hpp"
#include "Common.hpp"
#include "InetAddr.hpp"
#include "ThreadPool.hpp"#define BACKLOG 8// using namespace LogModule;
using namespace ThreadPoolModule;
static const uint16_t gport = 8080;
using handler_t = std::function<std::string(std::string)>;class TcpServer
{using task_t = std::function<void()>;struct ThreadData{int sockfd;TcpServer *self;};
public:TcpServer(handler_t handler, int port = gport):_handler(handler), _port(port),_isrunning(false){}void InitServer(){// 先监听_listensockfd = ::socket(AF_INET, SOCK_STREAM, 0);if(_listensockfd < 0){LOG(LogLevel::FATAL)<<"socket error";Die(SOCKET_ERR);}LOG(LogLevel::INFO)<<"socket create success, _listensocked is "<<_listensockfd;// 后bindstruct sockaddr_in local;// 网络通信用sockaddr_in, 本地用sockaddr_unmemset(&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, CONV(&local), sizeof(local));if(n < 0){LOG(LogLevel::FATAL)<<"bind error";Die(BIND_ERR);}LOG(LogLevel::INFO) << "bind success, sockfd is: "<<_listensockfd;// 设置为监听状态n = listen(_listensockfd, BACKLOG);if(n < 0){LOG(LogLevel::FATAL)<<"listen error";Die(LISTEN_ERR);}LOG(LogLevel::INFO)<<"listen success, socked is:"<<_listensockfd;// 此处可使用::signal(SIGCHLD, SIG_IGN)来将父子进程解绑}void HandlerRequest(int sockfd){LOG(LogLevel::INFO)<<"HandlerRequest, sockfd is:"<<sockfd;char inbuffer[4096];while(true){ssize_t n = recv(sockfd, inbuffer, sizeof inbuffer, 0);inbuffer[n] = 0;LOG(LogLevel::INFO)<<"server recived:"<<inbuffer;if(n > 0){inbuffer[n] = 0;std::string cmd_result = _handler(inbuffer);// 回调::send(sockfd, cmd_result.c_str(), cmd_result.size(), 0);LOG(LogLevel::INFO)<<"server sent:"<<cmd_result;}else if(n == 0){LOG(LogLevel::INFO)<<"client quit"<<sockfd;break;}else{break;}}::close(sockfd);// 防止fd泄露}static void *ThreadEntry(void *args)// 设为静态函数就不用传递this{// 当使用多线程(不是封装好的线程池), pthread_thread_create的函数只能接收一个参数pthread_detach(pthread_self());ThreadData *data = (ThreadData *)args;data->self->HandlerRequest(data->sockfd);return nullptr;}void Start(){_isrunning = true;while(_isrunning){struct sockaddr_in peer;socklen_t peerlen = sizeof(peer);LOG(LogLevel::DEBUG)<<"accepting...";int sockfd = ::accept(_listensockfd, CONV(&peer), &peerlen);if(sockfd < 0){LOG(LogLevel::WARNING)<<"accept error:"<<strerror(errno);continue;}// 连接成功LOG(LogLevel::INFO)<<"accept success, sockfd is:"<<sockfd;InetAddr addr(peer);LOG(LogLevel::INFO)<<"client info:"<<addr.Addr();// 使用线程池实现ThreadPool<task_t>::getInstance()->Equeue([this, sockfd](){this->HandlerRequest(sockfd);});}   }~TcpServer(){}private:int _listensockfd;// 监听socketuint16_t _port;bool _isrunning;// 处理上层任务入口handler_t _handler;
};

TcpClient.cc

#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>// #include "Common.hpp"int main(int argc, char *argv[])
{if(argc != 3){std::cout<<"Usage:./client_tcp [server_ip] [server_port]"<<std::endl;return 1;}std::string server_ip = argv[1];int server_port = std::stoi(argv[2]);int sockfd = ::socket(AF_INET, SOCK_STREAM, 0);if(sockfd < 0){std::cout<<"create socket failed"<<std::endl;return 2;}struct sockaddr_in server_addr;memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(server_port);server_addr.sin_addr.s_addr = inet_addr(server_ip.c_str());// client 不需要显示进行 bind, tcp是面向连接的, connect底层自动bindint n = ::connect(sockfd, (struct sockaddr*)(&server_addr), sizeof(server_addr));if(n < 0){std::cout<<"connet falied"<<std::endl;return 3;}std::cout<<"connet 成功\n"<<std::endl;std::string message;while(true){  char inbuffer[1024];std::cout<<"input message: ";std::getline(std::cin, message);n = ::write(sockfd, message.c_str(), message.size());if(n > 0){int m = read(sockfd, inbuffer, sizeof(inbuffer));if(m > 0){inbuffer[m] = 0;std::cout<<inbuffer<<std::endl;}else break;}else break;}::close(sockfd);return 0;
}

CommadExec.hpp

#pragma once #include <iostream>
#include <string>class Command
{
public:std::string Execute(std::string cmdstr){return std::string("命令执行完毕\n");}
};

Common.hpp

#pragma once 
#include <iostream>
#define Die(code) do{exit(code);}while(0)
#define CONV(v) (struct sockaddr *)(v)enum
{USAGE_ERR = 1, SOCKET_ERR,BIND_ERR,LISTEN_ERR
};bool SplitString(std::string &in, std::string *key, std::string *val, std::string gap)
{size_t pos = in.find(gap);if (pos == std::string::npos) return false;*key = in.substr(0, pos);*val = in.substr(pos + gap.size());if(key->empty() || val->empty()) return false;return true;
}

相关文章:

Tcp_socket

Tcp不保证报文完整性&#xff08;面向字节流&#xff09; 所以我们需要在应用层指定协议&#xff0c;确保报文完整性 // {json} -> len\r\n{json}\r\n bool Encode(std::string &message) {if(message.size() 0) return false;std::string package std::to_string(m…...

idea插件开发,如何获取idea设置的系统语言

手打不易&#xff0c;如果转摘&#xff0c;请注明出处&#xff01; 注明原文&#xff1a;https://zhangxiaofan.blog.csdn.net/article/details/145578160 版本要求 大于 2024.3 错误用法 网上有的说使用&#xff1a;UIUtil com.intellij.util.ui.UIUtil 代码示例&#xf…...

< 自用文儿 > 在 Ubuntu 24 卸载 Docker 应用软件与运行的容器

环境&#xff1a; Host: usw OS: Ubuntu 24.04 TLS 目标: 卸载在运行的 Docker APP。 &#xff08;上运行了一个 container: 可以在线看 WSJ RSS 新闻&#xff0c;都 docker 预装两个网口&#xff0c;今天发现路由表有些看不懂&#xff0c;决定卸载&#xff09; 卸载 Dock…...

基于 SpringBoot 和 Vue 的智能腰带健康监测数据可视化平台开发(文末联系,整套资料提供)

基于 SpringBoot 和 Vue 的智能腰带健康监测数据可视化平台开发 一、系统介绍 随着人们生活水平的提高和健康意识的增强&#xff0c;智能健康监测设备越来越受到关注。智能腰带作为一种新型的健康监测设备&#xff0c;能够实时采集用户的腰部健康数据&#xff0c;如姿势、运动…...

MySQL InnoDB引擎 MVCC

MVCC&#xff08;Multi-Version Concurrency Control&#xff09;即多版本并发控制&#xff0c;是 MySQL 的 InnoDB 存储引擎实现并发控制的一种重要技术。它在很多情况下避免了加锁操作&#xff0c;从而提高了数据库的并发性能。 一、原理 MVCC 的核心思想是通过保存数据在某…...

深入解析 STM32 GPIO:结构、配置与应用实践

理解 GPIO 的工作原理和配置方法是掌握 STM32 开发的基础&#xff0c;后续的外设&#xff08;如定时器、ADC、通信接口&#xff09;都依赖于 GPIO 的正确配置。 目录 一、GPIO 的基本概念 二、GPIO 的主要功能 三、GPIO 的内部结构 四、GPIO 的工作模式 1. 输入模式 2. 输…...

【Elasticsearch】管道聚合

管道聚合就是在已有聚合结果之上在进行聚合&#xff0c;管道聚合是针对于聚合的聚合 在 Elasticsearch 中&#xff0c;管道聚合&#xff08;Pipeline Aggregations&#xff09;是一种特殊的聚合类型&#xff0c;用于对其他聚合的结果进行进一步的计算和处理&#xff0c;而不是直…...

Python的那些事第十八篇:框架与算法应用研究,人工智能与机器学习

人工智能与机器学习&#xff1a;框架与算法应用研究 摘要 本文深入探讨了人工智能与机器学习领域的核心框架和技术&#xff0c;包括TensorFlow、PyTorch和Scikit-learn库。文章首先介绍了TensorFlow和PyTorch的安装与配置方法&#xff0c;详细阐述了它们的基础概念&#xff0c…...

【大数据安全分析】为什么要用大数据技术进行安全分析?

在当今数字化浪潮的推动下,安全运营领域犹如一片广袤且复杂的战场。由于其涵盖范围极为宽泛,为了能更深入、精准地探讨相关内容,将目光聚焦于大数据安全分析方向显得尤为必要。一方面,大数据安全分析在安全运营领域占据着举足轻重的地位;另一方面,倘若自身对该领域较为熟…...

java微服务常用技术

Spring Cloud Alibaba 1 系统架构演进 随着互联网行业的发展,对服务的要求也越来越高,服务架构也从单体架构逐渐演变为现在流行的微服务架构。 1.1 单体架构 早期的软件系统通常是基于单体应用架构设计的,也就是将整个系统作为一个单一的、可执行的应用程序来构建和维护…...

【Qt 常用控件】多元素控件(QListWidget、QTabelWidgt、QTreeWidget)

**View和**Widget的区别&#xff1f; **View的实现更底层&#xff0c;**Widget是基于**View封装实现的更易用的类型。 **View使用MVC结构 MVC是软件开发中 经典的 软件结构 组织形式&#xff0c;软件设计模式。 M&#xff08;model&#xff09;模型。管理应用程序的核心数据和…...

ubuntu文件同步

1. 使用 rsync 同步文件 rsync 是一个常用的文件同步工具&#xff0c;可以在本地或远程系统之间同步文件和目录。 基本用法&#xff1a; rsync -avz /源目录/ 目标目录/-a&#xff1a;归档模式&#xff0c;保留文件属性。-v&#xff1a;显示详细输出。-z&#xff1a;压缩传输…...

解决VsCode的 Vetur 插件has no default export Vetur问题

文章目录 前言1.问题2. 原因3. 解决其他 前言 提示&#xff1a; 1.问题 Cannot find module ‘ant-design-vue’. Did you mean to set the ‘moduleResolution’ option to ‘node’, or to add aliases to the ‘paths’ option? Module ‘“/xxx/xxx/xxx/xxx/xxx/src/vie…...

DeepSeek本地部署详细指南

DeepSeek本地部署详细指南 随着人工智能技术的飞速发展&#xff0c;本地部署大模型的需求也日益增加。DeepSeek作为一款开源且性能强大的大语言模型&#xff0c;提供了灵活的本地部署方案&#xff0c;让用户能够在本地环境中高效运行模型&#xff0c;同时保护数据隐私。以下是…...

DNS污染:网络世界的“隐形劫持”与防御

在互联网的底层架构中&#xff0c;DNS&#xff08;域名系统&#xff09;如同数字世界的“导航员”&#xff0c;将用户输入的域名翻译成机器可读的IP地址。然而&#xff0c;DNS污染&#xff08;DNS Poisoning&#xff09;正像一场无声的“地址篡改”危机&#xff0c;威胁着全球网…...

AF3 superimpose函数解读

AlphaFold3 superimpose函数通过使用SVD最小化RMSD&#xff0c;将坐标叠加到参考上&#xff0c;在蛋白质结构预测中用于比较预测结构与真实结构的相似性。 源代码&#xff1a; from src.utils.geometry.alignment import weighted_rigid_align from src.utils.geometry.vect…...

python制作自己的一款Markdowm格式消除工具

01 引言 在日常使用 Markdown 编写文档时&#xff0c;我们有时会需要将 Markdown 格式的文本转换为纯文本&#xff0c;去除其中的各种标记符号&#xff0c;如标题符号、列表符号、代码块标记等。手动去除这些标记不仅效率低下&#xff0c;还容易出错。本文将介绍如何使用 Pyt…...

【C#零基础从入门到精通】(三)——C#变量和数据类型详解

【C#零基础从入门到精通】(三)——C#变量和数据类型详解 数据类型 在 C# 中,数据类型是对数据进行分类的方式,它定义了变量可以存储的数据的种类、范围以及可以对这些数据执行的操作。C# 的数据类型主要分为值类型、引用类型和指针类型(指针类型通常在不安全代码中使用),…...

如何从头训练大语言模型: A simple technical report

今天来快速捋一下路线&#xff0c;写个简短的technical report&#xff0c;更多是原理介绍性的。按我个人理解&#xff0c;从最简单的部分开始&#xff0c;逐步过渡到最繁复的环节: 模型架构-> Pretrain -> Post-Train -> Infra -> 数据侧。再掺杂一些杂项&#xf…...

gitlab无法登录问题

在我第一次安装gitlab的时候发现登录页面是 正常的页面应该是 这种情况的主要原因是不是第一次登录&#xff0c;所以我们要找到原先的密码 解决方式&#xff1a; [rootgitlab ~]# vim /etc/gitlab/initial_root_password# WARNING: This value is valid only in the followin…...

食品饮料生产瓶颈?富唯智能协作机器人来 “破壁”

在食品和饮料行业的发展进程中&#xff0c;诸多生产瓶颈如重复性劳动负担、复杂环境作业难题、季节性产能波动等&#xff0c;长期制约着企业的高效运营与进一步发展。如今&#xff0c;富唯智能协作机器人的出现&#xff0c;为这些难题提供了完美的解决方案&#xff0c;正逐步改…...

Python 实现 macOS 系统代理的设置

设置 SOCKS 代理 在 macOS 系统中&#xff0c;可以通过 networksetup 工具来设置 SOCKS 代理。以下是 Python 实现的方法&#xff1a; 使用 networksetup 设置 SOCKS 代理 import subprocessdef set_socks_proxy(server, port):"""设置 macOS 系统的 SOCKS 代理…...

深度学习之神经网络框架搭建及模型优化

神经网络框架搭建及模型优化 目录 神经网络框架搭建及模型优化1 数据及配置1.1 配置1.2 数据1.3 函数导入1.4 数据函数1.5 数据打包 2 神经网络框架搭建2.1 框架确认2.2 函数搭建2.3 框架上传 3 模型优化3.1 函数理解3.2 训练模型和测试模型代码 4 最终代码测试4.1 SGD优化算法…...

excel 日期转换

需求如下&#xff1a; 在excel 里面输入一个4515,4表示年份&#xff0c;2024年&#xff0c;51表示该年的51周&#xff0c;5表示日&#xff0c;周日用1表示&#xff0c;周一用2表示&#xff0c;以此类推&#xff0c;需要转换为年份/月份/日期 若想用公式来实现这一转换&#x…...

Awtk 如何添加开机画面

场景 我们知道在工程中&#xff0c;Ui是一个线程&#xff0c;并且需要一直存在&#xff0c;当我们使用的开机画面在这个线程开启就直接展示的时候&#xff0c;因为awtk的界面是window_open入栈的&#xff0c;即首次打开的窗口会记录在top&#xff0c;往后的窗口会依次往后存放&…...

【设计模式】【行为型模式】命令模式(Command)

&#x1f44b;hi&#xff0c;我不是一名外包公司的员工&#xff0c;也不会偷吃茶水间的零食&#xff0c;我的梦想是能写高端CRUD &#x1f525; 2025本人正在沉淀中… 博客更新速度 &#x1f4eb; 欢迎V&#xff1a; flzjcsg2&#xff0c;我们共同讨论Java深渊的奥秘 &#x1f…...

C++模拟实现AVL树

目录 1.文章概括 2.AVL树概念 3.AVL树的性质 4.AVL树的插入 5.旋转控制 1.左单旋 2. 右单旋 3.左右双旋 4.右左双旋 6.全部代码 1.文章概括 本文适合理解平衡二叉树的读者阅读&#xff0c;因为AVL树是平衡二叉树的一种优化&#xff0c;其大部分实现逻辑与平衡二叉树是…...

推荐算法实践:movielens数据集

MovieLens 数据集介绍 MovieLens 数据集是由明尼苏达大学的GroupLens研究小组维护的一个广泛使用的电影评分数据集&#xff0c;主要用于推荐系统的研究。该数据集包含用户对电影的评分、标签以及其他相关信息&#xff0c;是电影推荐系统开发与研究的常用数据源。 数据集版本 …...

dynamic_cast和static_cast和const_cast

dynamic_cast 在 C 中的作用 dynamic_cast 是 C 运行时类型转换&#xff08;RTTI, Run-Time Type Identification&#xff09;的一部分&#xff0c;主要用于&#xff1a; 安全的多态类型转换检查类型的有效性向下转换&#xff08;Downcasting&#xff09;跨类层次的指针或引用…...

React进行路由跳转的方法汇总

在 React 中进行路由跳转有多种方法&#xff0c;具体取决于你使用的路由库和版本。以下是常见的路由跳转方法汇总&#xff0c;主要基于 react-router-dom 库。 1. 使用 useNavigate 钩子&#xff08;适用于 react-router-dom v6&#xff09; useNavigate 是 react-router-dom…...