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中,把上三层归为 应用层
最后二层归为 网卡 层
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不保证报文完整性(面向字节流) 所以我们需要在应用层指定协议,确保报文完整性 // {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设置的系统语言
手打不易,如果转摘,请注明出处! 注明原文:https://zhangxiaofan.blog.csdn.net/article/details/145578160 版本要求 大于 2024.3 错误用法 网上有的说使用:UIUtil com.intellij.util.ui.UIUtil 代码示例…...
< 自用文儿 > 在 Ubuntu 24 卸载 Docker 应用软件与运行的容器
环境: Host: usw OS: Ubuntu 24.04 TLS 目标: 卸载在运行的 Docker APP。 (上运行了一个 container: 可以在线看 WSJ RSS 新闻,都 docker 预装两个网口,今天发现路由表有些看不懂,决定卸载) 卸载 Dock…...
基于 SpringBoot 和 Vue 的智能腰带健康监测数据可视化平台开发(文末联系,整套资料提供)
基于 SpringBoot 和 Vue 的智能腰带健康监测数据可视化平台开发 一、系统介绍 随着人们生活水平的提高和健康意识的增强,智能健康监测设备越来越受到关注。智能腰带作为一种新型的健康监测设备,能够实时采集用户的腰部健康数据,如姿势、运动…...
MySQL InnoDB引擎 MVCC
MVCC(Multi-Version Concurrency Control)即多版本并发控制,是 MySQL 的 InnoDB 存储引擎实现并发控制的一种重要技术。它在很多情况下避免了加锁操作,从而提高了数据库的并发性能。 一、原理 MVCC 的核心思想是通过保存数据在某…...
深入解析 STM32 GPIO:结构、配置与应用实践
理解 GPIO 的工作原理和配置方法是掌握 STM32 开发的基础,后续的外设(如定时器、ADC、通信接口)都依赖于 GPIO 的正确配置。 目录 一、GPIO 的基本概念 二、GPIO 的主要功能 三、GPIO 的内部结构 四、GPIO 的工作模式 1. 输入模式 2. 输…...
【Elasticsearch】管道聚合
管道聚合就是在已有聚合结果之上在进行聚合,管道聚合是针对于聚合的聚合 在 Elasticsearch 中,管道聚合(Pipeline Aggregations)是一种特殊的聚合类型,用于对其他聚合的结果进行进一步的计算和处理,而不是直…...
Python的那些事第十八篇:框架与算法应用研究,人工智能与机器学习
人工智能与机器学习:框架与算法应用研究 摘要 本文深入探讨了人工智能与机器学习领域的核心框架和技术,包括TensorFlow、PyTorch和Scikit-learn库。文章首先介绍了TensorFlow和PyTorch的安装与配置方法,详细阐述了它们的基础概念,…...
【大数据安全分析】为什么要用大数据技术进行安全分析?
在当今数字化浪潮的推动下,安全运营领域犹如一片广袤且复杂的战场。由于其涵盖范围极为宽泛,为了能更深入、精准地探讨相关内容,将目光聚焦于大数据安全分析方向显得尤为必要。一方面,大数据安全分析在安全运营领域占据着举足轻重的地位;另一方面,倘若自身对该领域较为熟…...
java微服务常用技术
Spring Cloud Alibaba 1 系统架构演进 随着互联网行业的发展,对服务的要求也越来越高,服务架构也从单体架构逐渐演变为现在流行的微服务架构。 1.1 单体架构 早期的软件系统通常是基于单体应用架构设计的,也就是将整个系统作为一个单一的、可执行的应用程序来构建和维护…...
【Qt 常用控件】多元素控件(QListWidget、QTabelWidgt、QTreeWidget)
**View和**Widget的区别? **View的实现更底层,**Widget是基于**View封装实现的更易用的类型。 **View使用MVC结构 MVC是软件开发中 经典的 软件结构 组织形式,软件设计模式。 M(model)模型。管理应用程序的核心数据和…...
ubuntu文件同步
1. 使用 rsync 同步文件 rsync 是一个常用的文件同步工具,可以在本地或远程系统之间同步文件和目录。 基本用法: rsync -avz /源目录/ 目标目录/-a:归档模式,保留文件属性。-v:显示详细输出。-z:压缩传输…...
解决VsCode的 Vetur 插件has no default export Vetur问题
文章目录 前言1.问题2. 原因3. 解决其他 前言 提示: 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本地部署详细指南 随着人工智能技术的飞速发展,本地部署大模型的需求也日益增加。DeepSeek作为一款开源且性能强大的大语言模型,提供了灵活的本地部署方案,让用户能够在本地环境中高效运行模型,同时保护数据隐私。以下是…...
DNS污染:网络世界的“隐形劫持”与防御
在互联网的底层架构中,DNS(域名系统)如同数字世界的“导航员”,将用户输入的域名翻译成机器可读的IP地址。然而,DNS污染(DNS Poisoning)正像一场无声的“地址篡改”危机,威胁着全球网…...
AF3 superimpose函数解读
AlphaFold3 superimpose函数通过使用SVD最小化RMSD,将坐标叠加到参考上,在蛋白质结构预测中用于比较预测结构与真实结构的相似性。 源代码: from src.utils.geometry.alignment import weighted_rigid_align from src.utils.geometry.vect…...
python制作自己的一款Markdowm格式消除工具
01 引言 在日常使用 Markdown 编写文档时,我们有时会需要将 Markdown 格式的文本转换为纯文本,去除其中的各种标记符号,如标题符号、列表符号、代码块标记等。手动去除这些标记不仅效率低下,还容易出错。本文将介绍如何使用 Pyt…...
【C#零基础从入门到精通】(三)——C#变量和数据类型详解
【C#零基础从入门到精通】(三)——C#变量和数据类型详解 数据类型 在 C# 中,数据类型是对数据进行分类的方式,它定义了变量可以存储的数据的种类、范围以及可以对这些数据执行的操作。C# 的数据类型主要分为值类型、引用类型和指针类型(指针类型通常在不安全代码中使用),…...
如何从头训练大语言模型: A simple technical report
今天来快速捋一下路线,写个简短的technical report,更多是原理介绍性的。按我个人理解,从最简单的部分开始,逐步过渡到最繁复的环节: 模型架构-> Pretrain -> Post-Train -> Infra -> 数据侧。再掺杂一些杂项…...
gitlab无法登录问题
在我第一次安装gitlab的时候发现登录页面是 正常的页面应该是 这种情况的主要原因是不是第一次登录,所以我们要找到原先的密码 解决方式: [rootgitlab ~]# vim /etc/gitlab/initial_root_password# WARNING: This value is valid only in the followin…...
食品饮料生产瓶颈?富唯智能协作机器人来 “破壁”
在食品和饮料行业的发展进程中,诸多生产瓶颈如重复性劳动负担、复杂环境作业难题、季节性产能波动等,长期制约着企业的高效运营与进一步发展。如今,富唯智能协作机器人的出现,为这些难题提供了完美的解决方案,正逐步改…...
Python 实现 macOS 系统代理的设置
设置 SOCKS 代理 在 macOS 系统中,可以通过 networksetup 工具来设置 SOCKS 代理。以下是 Python 实现的方法: 使用 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 日期转换
需求如下: 在excel 里面输入一个4515,4表示年份,2024年,51表示该年的51周,5表示日,周日用1表示,周一用2表示,以此类推,需要转换为年份/月份/日期 若想用公式来实现这一转换&#x…...
Awtk 如何添加开机画面
场景 我们知道在工程中,Ui是一个线程,并且需要一直存在,当我们使用的开机画面在这个线程开启就直接展示的时候,因为awtk的界面是window_open入栈的,即首次打开的窗口会记录在top,往后的窗口会依次往后存放&…...
【设计模式】【行为型模式】命令模式(Command)
👋hi,我不是一名外包公司的员工,也不会偷吃茶水间的零食,我的梦想是能写高端CRUD 🔥 2025本人正在沉淀中… 博客更新速度 📫 欢迎V: flzjcsg2,我们共同讨论Java深渊的奥秘 …...
C++模拟实现AVL树
目录 1.文章概括 2.AVL树概念 3.AVL树的性质 4.AVL树的插入 5.旋转控制 1.左单旋 2. 右单旋 3.左右双旋 4.右左双旋 6.全部代码 1.文章概括 本文适合理解平衡二叉树的读者阅读,因为AVL树是平衡二叉树的一种优化,其大部分实现逻辑与平衡二叉树是…...
推荐算法实践:movielens数据集
MovieLens 数据集介绍 MovieLens 数据集是由明尼苏达大学的GroupLens研究小组维护的一个广泛使用的电影评分数据集,主要用于推荐系统的研究。该数据集包含用户对电影的评分、标签以及其他相关信息,是电影推荐系统开发与研究的常用数据源。 数据集版本 …...
dynamic_cast和static_cast和const_cast
dynamic_cast 在 C 中的作用 dynamic_cast 是 C 运行时类型转换(RTTI, Run-Time Type Identification)的一部分,主要用于: 安全的多态类型转换检查类型的有效性向下转换(Downcasting)跨类层次的指针或引用…...
React进行路由跳转的方法汇总
在 React 中进行路由跳转有多种方法,具体取决于你使用的路由库和版本。以下是常见的路由跳转方法汇总,主要基于 react-router-dom 库。 1. 使用 useNavigate 钩子(适用于 react-router-dom v6) useNavigate 是 react-router-dom…...
