Linux网络 TCP socket
TCP简介
TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。它位于OSI模型的第四层,主要为应用层提供数据传输服务。TCP通过三次握手建立连接,确保数据在发送和接收过程中的准确性和顺序性。
TCP的主要特点
- 可靠性:TCP通过序列号、确认应答、超时重传等机制保证数据可靠传输。
- 面向连接:通信双方在传输数据前需要建立连接,通信结束后释放连接。
- 流量控制:通过滑动窗口机制,TCP可以控制数据的发送速度,避免接收方缓冲区溢出。
- 拥塞控制:TCP可以根据网络状况调整发送速率,减少网络拥塞。
- 全双工通信:TCP连接允许数据在两个方向上同时传输。
TCP与UDP的比较
与TCP不同,用户数据报协议(UDP)是无连接的、不可靠的传输层协议。UDP适用于对实时性要求高、但可以容忍少量数据丢失的应用,如视频通话、在线游戏等。而TCP则适用于对数据完整性要求高的应用,如文件传输、电子邮件等。
函数介绍
socket()
int socket(int domain, int type, int protocol);
- 功能:创建一个新的套接字。
- 参数说明:
domain
:指定协议族,如AF_INET
(IPv4)或AF_INET6
(IPv6)。type
:指定套接字类型,如SOCK_STREAM
(TCP)或SOCK_DGRAM
(UDP),由于使用TCP协议,所以使用SOCK_STREAM,表示面向流的传输协议。protocol
:指定协议类型,通常为 0,表示使用默认协议。
- 返回值:成功时返回一个新的套接字描述符,失败时返回 -1。该套接字描述符本质与文件描述符一样,应用程序可以像读写文件一样用 read/write 在网络上收发数据。
bind()
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
- 功能:将套接字绑定到指定的地址和端口。服务器程序所监听的网络地址和端口号通常是固定不变的,客户端程序得知服务器程序的地址和端口号后就可以向服务器发起连接; 服务器需要调用 bind 绑定一个固定的网络地址和端口号,客户端无需手动绑定。
- 参数说明:
sockfd
:由socket()
函数返回的套接字描述符。addr
:指向包含地址和端口信息的sockaddr
结构的指针。addrlen
:sockaddr
结构的长度。由于struct sockaddr *是一个通用指针类型,addr 参数实际上可以接受多种协议的 sockaddr 结构体,而它们的长度各不相同,所以需要第三个参数 addrlen指定结构体的长度。
struct sockaddr_in socket;
bzero(&socket,sizeof(socket)); //将整个结构体清零
socket.sin_family=AF_INET; //设置地址类型为 AF_INET
socket.sin_port=htons(SERVER_PORT); //设置端口号,如8080
socket.sin_addr.s_addr=inet_addr(SERVER_IP); //设置IP地址,
//如"127.0.0.1",如果地址为 INADDR_ANY, 这个宏表示本地的任意 IP
//地址,因为服务器可能有多个网卡,每个网卡也可能绑定多个 IP 地址,
//这样设置可以在所有的 IP 地址上监听, 直到与某个客户端建立了连接
//时才确定下来到底用哪个 IP 地址
- 返回值:成功时返回 0,失败时返回 -1。
listen()
int listen(int sockfd, int backlog);
- 功能:服务器开始监听连接请求。
- 参数说明:
sockfd
:由socket()
函数返回的套接字描述符。backlog
:指定连接请求队列的最大长度,最多允许有 backlog 个客户端处于连接等待状态, 如果接收到更多的连接请求就忽略。
- 返回值:成功时返回 0,失败时返回 -1。
int _listensockfd = socket(AF_INET, SOCK_STREAM, 0);// 创建socket
struct sockaddr_in socket;
bzero(&socket,sizeof(socket)); //将整个结构体清零
socket.sin_family=AF_INET; //设置地址类型为 AF_INET
socket.sin_port=htons(SERVER_PORT); //设置端口号,如8080
socket.sin_addr.s_addr=inet_addr(SERVER_IP);
int ret = bind(_listensockfd, (struct sockaddr *)&socket, sizeof(socket));
ret = listen(_listensockfd, BACKLOG);// 将socket设置为监听状态
accept()
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
- 功能:接受客户端的连接请求。
- 参数说明:
sockfd
:由socket()
函数返回的套接字描述符。addr
:指向用于存储客户端地址信息的sockaddr
结构的指针,如果给 addr 参数传NULL,表示不关心客户端的地址。addrlen
:指向sockaddr
结构长度的指针。
- 返回值:成功时返回一个新的套接字描述符,代表与客户端的连接,之后服务器和客户端之间的交流就通过该返回值进行,失败时返回 -1。
struct sockaddr_in peer;socklen_t peerlen = sizeof(peer);int sockfd = accept(_listensockfd, (struct sockaddr *)&peer, &peerlen);
connect()
int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);
- 功能:客户端连接到指定的服务器,connect 和 bind 的参数形式一致, 区别在于 bind 的参数是自己的地址, 而connect 的参数是对方的地址。
- 参数说明:
sockfd
:由socket()
函数返回的套接字描述符。serv_addr
:指向包含服务器地址信息的sockaddr
结构的指针。addrlen
:sockaddr
结构的长度。
- 返回值:成功时返回 0,失败时返回 -1。
// 填写网络信息
struct sockaddr_in server_addr;
bzero(&server_addr, 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,connect连接时自动bind
int n = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
send()
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
- 功能:发送数据到已连接的套接字。
- 参数说明:
sockfd
:由socket()
函数返回的套接字描述符。buf
:指向要发送数据的缓冲区的指针。len
:要发送的数据的长度。flags
:通常为 0,表示默认的发送行为。
- 返回值:成功时返回发送的字节数,失败时返回 -1。
recv()
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
- 功能:从已连接的套接字接收数据。
- 参数说明:
sockfd
:由socket()
函数返回的套接字描述符。buf
:指向用于接收数据的缓冲区的指针。len
:缓冲区的长度。flags
:通常为 0,表示默认的接收行为。
- 返回值:成功时返回接收的字节数,失败时返回 -1。
close()
int close(int sockfd);
- 功能:关闭套接字。
- 参数说明:
sockfd
:由socket()
函数返回的套接字描述符。
- 返回值:成功时返回 0,失败时返回 -1。
案例 多线程远程命令执行
makefile
all: server client
server:TcpServermain.ccg++ -o $@ $^ -std=c++17 -lpthread
client:TcpClient.ccg++ -o $@ $^ -std=c++17
.PHONY:clean
clean:rm -f server client
Mutex.hpp
#pragma once
#include <iostream>
#include <pthread.h>
using namespace std;class Mutex
{
public:Mutex(const Mutex&)=delete;const Mutex& operator=(const Mutex&)=delete;Mutex(){pthread_mutex_init(&_lock,nullptr);}~Mutex(){pthread_mutex_destroy(&_lock);}void Lock(){pthread_mutex_lock(&_lock);}pthread_mutex_t * LockPtr(){return &_lock;}void Unlock(){pthread_mutex_unlock(&_lock);}
private:pthread_mutex_t _lock;
};
class LockGuard
{public:LockGuard(Mutex& m):_mutex(m){_mutex.Lock();}~LockGuard(){_mutex.Unlock();}private:Mutex& _mutex;
};
Cond.hpp
#pragma once
#include"Mutex.hpp"
class Cond
{public:Cond(){pthread_cond_init(&_cond,nullptr);}~Cond(){pthread_cond_destroy(&_cond);}void Wait(Mutex& mutex){pthread_cond_wait(&_cond,mutex.LockPtr());}void Notify(){pthread_cond_signal(&_cond);}void NotifyAll(){pthread_cond_broadcast(&_cond);}private:pthread_cond_t _cond;
};
Thread.hpp
#pragma once
#include <pthread.h>
#include <iostream>
#include <functional>
#include <string>
#include <unistd.h>
using namespace std;
using func_t = function<void(string)>;
static int number = 1;
enum STATUS
{NEW,RUNNING,STOP
};
class Thread
{
private:static void *Routine(void *arg){Thread *t = static_cast<Thread *>(arg);t->_func(t->_name);return nullptr;}public:Thread(func_t func): _func(func), _status(NEW), _joinable(true){_name = "Thread-" + to_string(number++);_pid = getpid();}bool Start(){if (_status != RUNNING){_status = RUNNING;int n = pthread_create(&_tid, nullptr, Routine, this);if (n != 0){return false;}return true;}return false;}bool Stop(){if (_status == RUNNING){_status = STOP;int n = pthread_cancel(_tid);if (n != 0){return false;}return true;}return false;}bool Join(){if (_joinable){_status = STOP;int n = pthread_join(_tid, nullptr);if (n != 0){return false;}return true;}return false;}void Detach(){_joinable = false;pthread_detach(_tid);}string Name(){return _name;}
private:string _name;pthread_t _tid;pid_t _pid;STATUS _status;bool _joinable;func_t _func;
};
ThreadPool.hpp
#pragma once
#include <iostream>
#include <string>
#include <queue>
#include <vector>
#include <memory>
#include "Mutex.hpp"
#include "Cond.hpp"
#include "Thread.hpp"
using thread_t = shared_ptr<Thread>;
const static int defaultnum = 5;template <class T>
class ThreadPool
{
private:bool IsEmpty() { return _taskq.empty(); }void HandlerTask(string name){cout << "线程: " << name << ", 进入HandlerTask的逻辑" << endl;while (true){// 1. 拿任务T t;{LockGuard lockguard(_lock);while (IsEmpty() && _isrunning){_wait_num++;_cond.Wait(_lock);_wait_num--;}// 2. 任务队列为空 && 线程池退出了if (IsEmpty() && !_isrunning)break;t = _taskq.front();_taskq.pop();}// 2. 处理任务t(); // 规定,未来所有的任务处理,全部都是必须提供t()方法!}cout << "线程: " << name << " 退出";}ThreadPool(const ThreadPool<T> &) = delete;ThreadPool<T> &operator=(const ThreadPool<T> &) = delete;ThreadPool(int num = defaultnum) : _num(num), _wait_num(0), _isrunning(false){for (int i = 0; i < _num; i++){_threads.push_back(make_shared<Thread>(bind(&ThreadPool::HandlerTask, this, std::placeholders::_1)));cout << "构建线程" << _threads.back()->Name() << "对象 ... 成功" << endl;}}public:static ThreadPool<T> *getInstance(){if (instance == NULL){LockGuard lockguard(mutex);if (instance == NULL){cout << "单例首次被执行,需要加载对象..." << endl;instance = new ThreadPool<T>();instance->Start();}}return instance;}void Equeue(T in){LockGuard lockguard(_lock);if (!_isrunning)return;_taskq.push(in);if (_wait_num > 0)_cond.Notify();}void Start(){if (_isrunning)return;_isrunning = true;for (auto &thread_ptr : _threads){cout << "启动线程" << thread_ptr->Name() << " ... 成功";thread_ptr->Start();}}void Wait(){for (auto &thread_ptr : _threads){thread_ptr->Join();cout << "回收线程" << thread_ptr->Name() << " ... 成功";}}void Stop(){LockGuard lockguard(_lock);if (_isrunning){_isrunning = false; // 不工作// 1. 让线程自己退出(要唤醒) && // 2. 历史的任务被处理完了if (_wait_num > 0)_cond.NotifyAll();}}private:vector<thread_t> _threads;int _num;int _wait_num;std::queue<T> _taskq; // 临界资源Mutex _lock;Cond _cond;bool _isrunning;static ThreadPool<T> *instance;static Mutex mutex; // 只用来保护单例
};template <class T>
ThreadPool<T> *ThreadPool<T>::instance = NULL;
template <class T>
Mutex ThreadPool<T>::mutex; // 只用来保护单例
InetAddr.hpp
#pragma once
#include <string>
#include <iostream>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <cstring>
using namespace std;
class InetAddr
{
public:InetAddr();InetAddr(int port, string ip = ""): _port(port), _ip(ip){bzero(&_sockaddr, sizeof(_sockaddr));_sockaddr.sin_family = AF_INET;_sockaddr.sin_port = htons(_port);if (_ip.empty())_sockaddr.sin_addr.s_addr = INADDR_ANY;else_sockaddr.sin_addr.s_addr = inet_addr(_ip.c_str());}InetAddr(const struct sockaddr_in &sockaddr){_port = ntohs(sockaddr.sin_port);char buf[64];_ip = inet_ntop(AF_INET, &sockaddr.sin_addr, buf, sizeof(buf));}bool operator==(const InetAddr &other){return _ip == other._ip;}InetAddr operator=(const InetAddr &other){_ip = other._ip;_port = other._port;_sockaddr = other._sockaddr;return *this;}struct sockaddr *getSockaddr(){return (struct sockaddr *)&_sockaddr;}int getSockaddrLen(){return sizeof(_sockaddr);}const string &getIp(){return _ip;}int getPort(){return _port;}private:string _ip;int _port;struct sockaddr_in _sockaddr;
};
Common.hpp
enum
{SOCKET_ERROR=1,BIND_ERROR,LISTEN_ERROR,ACCEPT_ERROR,CONNECT_ERROR
};
TcpServer.hpp
#pragma once
#include <iostream>
#include <pthread.h>
#include <functional>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstring>
#include <memory>
#include "Common.hpp"
#include "InetAddr.hpp"
#include "ThreadPool.hpp"
using namespace std;#define BACKLOG 8
using handler_t = function<string(string)>;
static const uint16_t gport = 8080;class TcpServer
{using task_t = function<void()>;struct ThreadData{int sockfd;TcpServer *self;};public:TcpServer(handler_t handler, int port = gport): _handler(handler), _port(port), _isrunning(false){}void InitServer(){// 创建socket_listensockfd = socket(AF_INET, SOCK_STREAM, 0);if (_listensockfd < 0){cout << "socket error" << endl;exit(SOCKET_ERROR);}cout << "socket create success,sockfd is: " << _listensockfd << endl;// 填写IP端口struct sockaddr_in local;bzero(&local, sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(_port);local.sin_addr.s_addr = INADDR_ANY;// bindint ret = bind(_listensockfd, (struct sockaddr *)&local, sizeof(local));if (ret < 0){cout << "bind error" << endl;exit(BIND_ERROR);}cout << "bind success" << endl;// 将socket设置为监听状态ret = listen(_listensockfd, BACKLOG);if (ret < 0){cout << "listen error" << endl;exit(LISTEN_ERROR);}cout << "listen success" << endl;}void HandleRequest(int sockfd) // TCP为全双工通信{char buffer[1024];while (true){// int n = read(sockfd, buffer, sizeof(buffer) - 1);int n = recv(sockfd, buffer, sizeof(buffer) - 1, 0);if (n > 0){buffer[n] = 0;cout << buffer << endl;string cmd_result = _handler(buffer);// write(sockfd, cmd_result.c_str(), cmd_result.size());send(sockfd, cmd_result.c_str(), sizeof(cmd_result), 0);}else if (n == 0){// 如果读取的值为0,说明client退出cout << "client quit" << endl;break;}else{// 读取失败break;}}close(sockfd);}void Start(){_isrunning = true;while (_isrunning){// 获取新连接struct sockaddr_in peer;socklen_t peerlen = sizeof(peer);int sockfd = accept(_listensockfd, (struct sockaddr *)&peer, &peerlen);if (sockfd < 0){cout << "accept error" << endl;exit(ACCEPT_ERROR);}cout << "accept success,sockfd is: " << sockfd << endl;InetAddr addr(peer);cout << "client info: " << addr.getIp() << ":" << addr.getPort() << endl;// 将任务交给线程池ThreadPool<task_t>::getInstance()->Equeue([&](){this->HandleRequest(sockfd);});}}void Stop(){_isrunning = false;}private:int _listensockfd; // 监听socketuint16_t _port;bool _isrunning;// 处理上层任务的入口handler_t _handler;
};
TcpServermain.cc
#include "TcpServer.hpp"
#include "CommandExec.hpp"
int main()
{Command cmd;unique_ptr<TcpServer> server = make_unique<TcpServer>([&](string cmdstr){ return cmd.Execute(cmdstr); });server->InitServer();server->Start();return 0;
}
TcpClient.cc
#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <cstring>
using namespace std;
#include "Common.hpp"
//./client server_ip server_port
int main(int argc, char *argv[])
{if (argc != 3){cout << "Usage:./client server_ip server_port" << endl;return 0;}string server_ip = argv[1];int server_port = stoi(argv[2]);int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){cout << "socket create error" << endl;exit(SOCKET_ERROR);}// 填写网络信息struct sockaddr_in server_addr;bzero(&server_addr, 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,connect连接时自动bindint n = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));if (n < 0){cout << "connect error" << endl;exit(CONNECT_ERROR);}string message;while (true){char buffer[1024];cout << "input message: ";getline(cin, message);n = send(sockfd, message.c_str(), message.size(), 0);if (n > 0){int m = recv(sockfd, buffer, sizeof(buffer) - 1, 0);if (m > 0){buffer[m] = 0;cout << buffer;}elsebreak;}elsebreak;}close(sockfd);return 0;
}
相关文章:
Linux网络 TCP socket
TCP简介 TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。它位于OSI模型的第四层,主要为应用层提供数据传输服务。TCP通过三次握手建立连接,确保数据在发送和接收过程中的准确性和顺序…...

(一)相机标定——四大坐标系的介绍、对应转换、畸变原理以及OpenCV完整代码实战(C++版)
一、四大坐标系介绍 1,世界坐标系 从这个世界(world)的视角来看物体 世界坐标系是3D空间坐标,每个点的位置用 ( X w , Y w , Z w ) (X_w,Y_w,Z_w) (Xw,Yw,Zw)表示 2,相机坐标系 相机本身具有一个坐标系&…...

【Linux网络编程】高效I/O--I/O的五种类型
目录 I/O的概念 网络通信的本质 I/O的本质 高效I/O 五种I/O模型 阻塞I/O 非阻塞I/O 信号驱动I/O 多路转接/多路复用I/O 异步I/O 非阻塞I/O的实现 I/O的概念 网络通信的本质 网络通信的本质其实就是I/O I:表示input(输入)O:表示ou…...

企业级NoSQL数据库Redis
1.浏览器缓存过期机制 1.1 最后修改时间 last-modified 浏览器缓存机制是优化网页加载速度和减少服务器负载的重要手段。以下是关于浏览器缓存过期机制、Last-Modified 和 ETag 的详细讲解: 一、Last-Modified 头部 定义:Last-Modified 表示服务器上资源…...

Vscode:问题解决办法 及 Tips 总结
Visual Studio Code(简称VSCode)是一个功能强大的开源代码编辑器,广泛用于各种编程语言和开发场景,本博客主要记录在使用 VSCode 进行verilog开发时遇到的问题及解决办法,使用过程中的技巧 文章目录 扩展安装失败调试配…...
二十三种设计模式-装饰器模式
一、定义与核心思想 装饰器模式是一种结构型设计模式,其核心思想是动态地给一个对象添加一些额外的职责。通过这种方式,可以在不改变原有对象结构的基础上,灵活地增加新的功能,使得对象的行为可以得到扩展,同时又保持…...

架构思考与实践:从通用到场景的转变
在当今复杂多变的商业环境中,企业架构的设计与优化成为了一个关键议题。本文通过一系列随笔,探讨了业务架构的价值、从通用架构到场景架构的转变、恰如其分的架构设计以及如何避免盲目低效等问题。通过对多个实际案例的分析,笔者揭示了架构设…...

Spring MVC(一)
RestController RestController 是由 Controller 和 ResponseBody 两个注解构成的。 Spring 启动的时候会扫描所有包含 Controller 或者 RestController 注解的类,创建出对外的接口,这样外界就可以从这里与服务器实现交互,如果没有这个注解…...
vue3使用tsx渲染复杂逻辑的表单
前置 目前的应用场景是:检查项目是树结构,有的项目还需要动态显示对应的子集 项目用的是uniappvue3tsvite生成的app tsx模版 统一渲染入口 <script lang"ts">import uniForms from dcloudio/uni-ui/lib/uni-forms/uni-forms.vueimport…...
python助力WRF自动化运行
对大部分人而言,特别是新用户,WRF模式的安装繁琐且不必要,可以作为后续进阶掌握的技能,本学习跳过繁琐的安装步骤,直接聚焦模式的运行部分,通过短平快的教学,快速掌握模式运行。进一步将python语…...
Windows 下 Postgres 安装 TimescaleDB 插件
Windows 下 Postgres 安装 TimescaleDB 插件 一、准备工作 安装 PostgreSQL:首先确保你已经在 Windows 系统中成功安装了 PostgreSQL 数据库。可以从 PostgreSQL 官方网站下载适合你系统的安装包,并按照安装向导进行安装。安装过程中,记住设…...

【Vim Masterclass 笔记21】S09L39:Vim 设置与 vimrc 文件的用法示例(二)
文章目录 S09L39 Vim Settings and the Vimrc File - Part 21 Vim 的配色方案与 color 命令2 map 命令3 示例:用 map 命令快速生成 HTML 代码片段4 Vim 中的 Leader 键5 用 mkvimrc 命令自动生成配置文件 写在前面 本篇为 Vim 自定义配置的第二部分。当中的每个知识…...
【Docker】Supervisor 实现单容器运行多服务进程
本文内容均来自个人笔记并重新梳理,如有错误欢迎指正! 如果对您有帮助,烦请点赞、关注、转发、订阅专栏! 专栏订阅入口 | 精选文章 | Kubernetes | Docker | Linux | 羊毛资源 | 工具推荐 | 往期精彩文章 【Docker】(全…...
【网络协议】【http】【https】ECDHE-TLS1.2
【网络协议】【http】【https】ECDHE-TLS1.2 ECDHE算法 1.客户端和服务器端事先确定好使用哪种椭圆曲线,和曲线上的基点G,这两个参数都是公开的, 双方各自随机生成一个随机数作为私钥d,并与基点 G相乘得到公钥Q(QdG),…...
(十五)WebGL中gl.texImage2D函数使用详解
在 WebGL 中,gl.texImage2D 是一个非常关键的函数,用于将图像数据上传到 WebGL 上下文中并作为纹理对象的一部分。它允许你将图像、视频、画布等作为纹理源。理解如何使用 gl.texImage2D 是在 WebGL 中处理纹理的核心之一。 文章目录 gl.texImage2D 的基…...
CSS 颜色
所有浏览器都支持的颜色名 所有现代浏览器均支持以下 140 种颜色名称(单击颜色名称或十六进制值,可查看将以该颜色为背景颜色以及不同的文本颜色): 颜色名十六进制颜色值颜色AliceBlue#F0F8FFAntiqueWhite#FAEBD7Aqua#00FFFFAqu…...

C#,入门教程(03)——Visual Studio 2022编写彩色Hello World与动画效果
C#,入门教程(01)—— Visual Studio 2022 免费安装的详细图文与动画教程https://blog.csdn.net/beijinghorn/article/details/123350910 C#,入门教程(02)—— Visual Studio 2022开发环境搭建图文教程https://blog.csdn.net/beijinghorn/article/detail…...

杀死安装 CentOS-7-x86_64-DVD-1908
使用 VMware 安装 CentOS-7-x86_64-DVD-1908 CentOS是 reahat 的 免费版本,有了ubutun ,为什么还要使用 CentOS呢? 在linux 服务器实际开发中,大家都用的CentOS,因为两个原因,一个是免费,第二是…...

55.【5】BUUCTF WEB NCTF2019 sqli
进入靶场 输入admin 123 过滤的这么严格??? 过滤很严格,此时要么爆破,要么扫描 直接扫描,得到robots.txt 访问后又得到hint.txt 继续访问 图片内容如下 $black_list "/limit|by|substr|mid|,|admi…...

LeetCode 题目 2545. 根据第 K 场考试的分数排序
在本篇文章中,我们将探讨如何根据第 K 场考试的分数对学生进行排序。这个问题是 LeetCode 上的一个中等难度问题,涉及到排序算法和自定义比较函数的使用。 问题描述 解题思路 理解问题 首先,我们需要理解问题的核心:根据第 K 场…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...

云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

莫兰迪高级灰总结计划简约商务通用PPT模版
莫兰迪高级灰总结计划简约商务通用PPT模版,莫兰迪调色板清新简约工作汇报PPT模版,莫兰迪时尚风极简设计PPT模版,大学生毕业论文答辩PPT模版,莫兰迪配色总结计划简约商务通用PPT模版,莫兰迪商务汇报PPT模版,…...

R 语言科研绘图第 55 期 --- 网络图-聚类
在发表科研论文的过程中,科研绘图是必不可少的,一张好看的图形会是文章很大的加分项。 为了便于使用,本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中,获取方式: R 语言科研绘图模板 --- sciRplothttps://mp.…...
提升移动端网页调试效率:WebDebugX 与常见工具组合实践
在日常移动端开发中,网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时,开发者迫切需要一套高效、可靠且跨平台的调试方案。过去,我们或多或少使用过 Chrome DevTools、Remote Debug…...

VisualXML全新升级 | 新增数据库编辑功能
VisualXML是一个功能强大的网络总线设计工具,专注于简化汽车电子系统中复杂的网络数据设计操作。它支持多种主流总线网络格式的数据编辑(如DBC、LDF、ARXML、HEX等),并能够基于Excel表格的方式生成和转换多种数据库文件。由此&…...