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

Linux系统编程—socket网络编程

Linux系统编程—socket网络编程

  • 理论概念
    • 1. TCP与UDP对比
    • 端口号作用
  • socket开发过程
  • 服务端
    • 1. socket 创建套接字
    • 2. bind 绑定IP+端口
    • 3. listen 监听客户端
    • 4. accept 接收客户端
    • 5. read / write 数据传输
  • 客户端
    • 1. socket 创建套接字
    • 2. connect 连接服务
    • 3. read / write 数据传输
  • server.c与client.c程序案例

理论概念

1. TCP与UDP对比

  • TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需 要建立连接

  • TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付

  • TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的
    UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)

  • 每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信

  • TCP首部开销20字节;UDP的首部开销小,只有8个字节

  • TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道

端口号作用

  • 一台拥有IP地址的主机可以提供许多服
    ,比如Web服务、FTP服务、SMTP服务等

  • 通过“IP地址+端口号”来区 分不同的服务,端口提供了一种访问通道,服务器一般都是通过端口号来识别的。

socket开发过程

在这里插入图片描述

服务端

1. socket 创建套接字

函数原型

	#include <sys/types.h>          #include <sys/socket.h>int socket(int domain, int type, int protocol);

返回值: 成功返回网络标识符,失败返回 -1
参数分析
domain: 指明所使用的协议族,通常为AF_INET,表示互联网协议族(TCP/IP协议族):

  • AF_INET IPv4因特网域
  • AF_INET6 IPv6 因特网域
  • AF_UNIX Unix 域
  • AF_ROUTE 路由套接字
  • AF_KEY 密钥套接字
  • AF_UNSPEC 未指定

type: 指定socket类型

  • SOCK_STREAM
      流式套接字提供可靠的、面向连接的通信流,它使用 TCP 协议,从而保证了数据传输的正确性和顺序性
  • SOCK_DGRAM
      数据报套接字定义了一种无连接的数据,数据通过相互独立的报文进行传输,是无序的,并且不保证是可靠、无差错的。它使用数据报协议UDP
  • SOCK_RAW
      允许程序使用低层协议,原始套接字允许对底层协议如 IP 或ICMP 进行直接访问,功能强大但使用较为不便,主要用于一些协议的开发。

protocol:
通常赋值 0

  • 0 选择 type 类型对应的默认协议
  • IPPROTO_TCP TCP 传输协议
  • IPPROTO_UDP UDP 传输协议
  • IPPROTO_SCTP SCTP 传输协议
  • IPPROTO_TIPC TIPC 传输协议

2. bind 绑定IP+端口

  • 功能:用于绑定IP地址和端口号到sockfd

函数原型

       #include <sys/types.h>          #include <sys/socket.h>int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);//成功返回0,失败返回-1

参数分析

参数类型/值
sockfd服务端网络标识符,即 socket 的返回值
struct sockaddr *addr绑定服务器端 网络协议、IP 地址和端口号的地址结构指针
socklen_t addrlen结构体大小
  • addr
      一个指向包含有本机 IP 地址及端口号等信息的 sockaddr 类型的指针,指向要绑定给 sockfd 的协议地址结构,这个地址结构根据地址创建socket 时的地址协议族的不同而不同

注:
IPV4的实际结构体如下

struct sockaddr {sa_family_t sa_family;char        sa_data[14];
}

同等替换为:

		struct sockaddr_in {sa_family_t       sin_family;    //协议族in_port_t         sin_port;      //端口号struct in_addr    sin_port;      //IP地址结构体unsigned char     sin_zero[8];   //填充 无实际意义};

struct sockaddr_in 结构体已在Linux内核系统中定义,成员参数配置如下;

  • sa_family_t  sin_family
    协议族, TCP协议族,AF_INET

  • in_port_t    sin_port
    端口号, 类型为网络字节序,需利用htons函数进行转化为网络字节数
    例:s_addr.sin_port = htons(8888);

  • struct in_addr    sin_port
    IP地址结构体,struct in_addr 类型结构体
    系统中定义的struct in_addr 结构体

    	struct in_addr {__be32  s_addr;};
    

    将IP地址转化为网络能识别的格式函数原型:

    	#include <netinet/in.h>#include <arpa/inet.h>int inet_aton(const char* straddr,struct in_addr *addrp);
    

    转化典例

    	inet_aton("127.0.0.1", &s_addr.sin_addr );
    

    地址转化API

    	 int inet_aton(char *straddr,struct in_addr *addr)//将字符串形式的"127.0.0.1"转化为网络能识别的格式char *inet_ntoa(struct in_addr inaddr);//把网络格式的ip地址转化为字符串形式
    

结构体配置及bin函数整合实例

	struct sockaddr_in s_addr;		//结构体变量定义s_addr.sin_family = AF_INET;	//配置网络协议族,TCP协议inet_aton("127.0.0.1", &s_addr.sin_addr );	//配置结构体成员IP地址s_addr.sin_port = htons(8888);				//配置结构体成员端口号bind(s_fd, (struct sockaddr *)&s_addr, sizeof(struct sockaddr_in));	//绑定IP+端口号

3. listen 监听客户端

函数原型

	#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>int listen(int sockfd, int backlog);

参数分析

参数类型/值
sockfd服务端网络标识符
backlog允许的最大客户单请求个数

功能

  • 设置能处理的最大连接数,listen()并未开始接受连线,只是设置 socket 的 listen 模式,listen 函数只用于服务器端,服务器进程不知道要与谁连接,因此,它不会主动地要求与某个进程连接,只是一直监听是否有其他客户进程与之连接,然后响应该连接请求,并对它做出处理,一个服务进程可以同时处理多个客户进程的连接。主要就两个功能:将一个未连接的套接字转换为一个被动套接字(监听),规定内核为相应套接字排队的最大连接数。
  • 内核为任何一个给定监听套接字维护两个队列:
    • 未完成连接队列,每个这样的 SYN 报文段对应其中一项:已由某个客户端发出并到达服务器,而服务器正在等待完成相应的 TCP 三次握手过程。这些套接字处于SYN REVD 状态
    • 已完成连接队列,每个已完成 TCP 三次握手过程的客户端对应其中一项。这些套接字处于ESTABLISHED 状态

4. accept 接收客户端

函数原型

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

返回值: 成功返回接入的客户端网络标识符,失败返回-1
参数分析

参数类型/值
sockfd服务端网络标识符
struct sockaddr *addrstruct sockaddr 结构体类型地址,用来返回已连接的对端(客户端)的协议地址
socklen_t *addrlen客户端地址长度,但为地址,需先取长度,后取地址

例:

	addrlen = sizeof(struct sockaddr_in);c_fd = accept(s_fd, (struct sockaddr *)&c_addr, &addrlen);

5. read / write 数据传输

	#include <unistd.h>ssize_t read(int c_fd, void *buf, size_t count);ssize_t write(int c_fd, const void *buf, size_t count);  
  • 函数使用方法同Linux文件编程用法,参数主要为:网络标识符、读写Buf以及读写字节数
  • 详情请参考博文:Linux系统编程—文件API编程

客户端

1. socket 创建套接字

函数原型

	#include <sys/types.h>          #include <sys/socket.h>int socket(int domain, int type, int protocol);

返回值: 成功返回网络标识符,失败返回 -1
参数分析

  • domain: 指明所使用的协议族,通常为AF_INET,表示互联网协议族(TCP/IP协议族):
  • type: 指定socket类型,SOCK_STREAM 流式套接字提供可靠的、面向连接的通信流,它使用 TCP 协议,
  • protocol: 通常赋值 0 ,选择 type 类型对应的默认协议

2. connect 连接服务

  • 功能:该函数用于绑定之后的client 端(客户端),与服务器建立连接

函数原型

	#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);//成功返回0,失败返回-1

参数分析

参数类型/值
sockfd服务端网络标识符
struct sockaddr *addr服务器端的 IP 地址和端口号的地址结构指针
socklen_t addrlen地址长度常被设置为 sizeof(struct sockaddr_in)

结构体实际配置同服务端,案例如下

    struct sockaddr_in c_addr;		//定义结构体变量c_addr.sin_family = AF_INET;	//配置成员网络协议族inet_aton("127.0.0.1", &c_addr.sin_addr );	//配置结构体成员IP地址c_addr.sin_port = htons(8888);				//配置结构体成员端口号connect(c_fd, (struct sockaddr *)&c_addr, sizeof(struct sockaddr_in));	//绑定IP+端口号

3. read / write 数据传输

	#include <unistd.h>ssize_t read(int c_fd, void *buf, size_t count);ssize_t write(int c_fd, const void *buf, size_t count);  
  • 函数使用方法同Linux文件编程用法,参数主要为:网络标识符、读写Buf以及读写字节数

server.c与client.c程序案例

server.c

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main()
{int s_fd, c_fd;		//定义网络标识符int nread;			//读取字节数char readBuf[128]={0};	//读取缓存char msg[]="Return from server: I got your message!";	//发送缓存//定义网络结构体并初始化struct sockaddr_in s_addr;struct sockaddr_in c_addr;memset(&s_addr, 0, sizeof(struct sockaddr_in));memset(&c_addr, 0, sizeof(struct sockaddr_in));//1. socket 创建套接字s_fd  = socket(AF_INET, SOCK_STREAM, 0);	//创建套接字if(s_fd == -1){printf("socket error!\n");exit(-1);}//2.bind   绑定IP+端口号s_addr.sin_family = AF_INET;				//配置网络协议inet_aton("127.0.0.1", &s_addr.sin_addr );	//配置IP地址s_addr.sin_port = htons(8888);				//配置端口号bind(s_fd, (struct sockaddr *)&s_addr, sizeof(struct sockaddr_in));	//绑定IP+端口号//3.linsten  监听客户端接入listen(s_fd, 10);printf("listing......\n");//4.accept  接收客户端接入int addrlen = sizeof(struct sockaddr_in);c_fd = accept(s_fd, (struct sockaddr *)&c_addr, &addrlen);if(c_fd == -1){printf("c_fd error!\n");exit(-1);}elseprintf("connect client: %s\n",inet_ntoa(c_addr.sin_addr));//5.read memset(readBuf, '\0', 128);nread = read(c_fd, readBuf, 128);	//从客户端读取128字节数据到readBuf缓存if(nread == -1){printf("nread error\n");exit(-1);}printf("Receive: %d Byte context:%s\n",nread, readBuf);//6.writewrite(c_fd, msg, strlen(msg));	//应答客户端memset(msg,'\0',128);return 0;
}

client.c

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>int main()
{int c_fd;int nread;int addrlen;char readBuf[128]={0};char msg[]="hello world";struct sockaddr_in c_addr;memset(&c_addr, 0, sizeof(struct sockaddr_in));//1. socketc_fd  = socket(AF_INET, SOCK_STREAM, 0);if(c_fd == -1){printf("socket error!\n");exit(-1);}//2. connect 与服务器建立连接c_addr.sin_family = AF_INET;inet_aton("127.0.0.1", &c_addr.sin_addr );c_addr.sin_port = htons(8888);if( connect(c_fd, (struct sockaddr *)&c_addr, sizeof(struct sockaddr_in)) == -1){printf("connect error\n");exit(-1);}//3.writewrite(c_fd, msg, strlen(msg));memset(msg, '\0', 128);//4.readmemset(readBuf,'\0',128);nread = read(c_fd, readBuf, 128);if(nread == -1){printf("nread error\n");exit(-1);}printf("read from server: %d Byte  context:\n%s\n",nread, readBuf);return 0;
}

试问:如何实现双方自由聊天

  • 服务器通过创建子进程用于和每个不同的客户端进行数据交互,父进程负责接收后续接入的客户端
  • 子进程内部再次创建子进程用来发送数据,父进程则实时接收来自服务器的数据

server.c 核心代码

//4.accept
while(1)
{//父进程用于接收其他接入的客户端c_fd = accept(s_fd, (struct sockaddr *)&c_addr, &addrlen);if(c_fd == -1){printf("c_fd error!\n");exit(-1);}elseprintf("connect client: %s\n",inet_ntoa(c_addr.sin_addr));cnt++;if(fork() == 0)			//创建进程,子进程用于和客户端进行数据交互{if(fork() == 0)		//子进程用于向客户端发送数据{//writewhile(1){printf("Inputs: ");scanf("%s",msg);write(c_fd, msg, strlen(msg));memset(msg,'\0',128);}}else		//父进程用于接收来自客户端发送的数据{//readwhile(1){memset(readBuf, '\0', 128);nread = read(c_fd, readBuf, 128);if(nread == -1){printf("nread error\n");exit(-1);}printf("Receive: %d Byte context:%s\n",nread, readBuf);}}}
}

client.c 核心代码

while(1)
{if(fork() == 0)			//子进程用于向服务器发送数据{while(1)        //write{printf("Input: ");scanf("%s",msg);//gets(msg);write(c_fd, msg, strlen(msg));memset(msg, '\0', 128);}}else					{						//父进程用于接收服务器发送的数据while(1)    	//read    {memset(readBuf,'\0',128);nread = read(c_fd, readBuf, 128);if(nread == -1){printf("nread error\n");exit(-1);}printf("read from server: %d Byte  context:\n",nread);printf("%s\n",readBuf);}
}  

相关文章:

Linux系统编程—socket网络编程

Linux系统编程—socket网络编程 理论概念1. TCP与UDP对比端口号作用 socket开发过程服务端1. socket 创建套接字2. bind 绑定IP端口3. listen 监听客户端4. accept 接收客户端5. read / write 数据传输 客户端1. socket 创建套接字2. connect 连接服务3. read / write 数据传输…...

函数指针

函数指针是一种特殊类型的指针&#xff0c;它指向一个函数而不是指向数据。函数指针允许你在程序运行时动态地选择要调用的函数&#xff0c;这对于实现回调函数、事件处理、动态加载库和创建通用函数接口等任务非常有用。 1. 声明函数指针 要声明一个函数指针&#xff0c;你需…...

Linux——进程间信号(超级详解!!)

索引 一.初始信号1.什么是信号2.前后台进程3.信号的种类4.信号的管理 二.信号产生前1.验证键盘是可以产生信号的2.通过系统调用接口发送信号3.由软件条件产生信号4.硬件异常产生信号5.总结6.core dump 信号产生中1.信号在内核中的表示2.信号集操作函数 信号产生后1.了解内核态和…...

C++ STL库的介绍和使用

文章目录 C STL库的介绍和使用STL六大组件算法的分类迭代器 一个简单的例子容器和自定义类型容器嵌套容器常用容器stringvectordequestackqueuelistset/multisetpairmap/multimap 容器的使用时机函数对象&#xff08;仿函数&#xff09;谓词内建函数对象适配器bind2nd和bind1st…...

Excel数学、工程和科学计算插件:FORMULADESK Studio

如果 Excel 是您的武器 - 让我们磨砺您的剑&#xff01;为整天使用 Excel 的人们提供创新的 Excel 加载项&#xff0c;你需要这个 FORMULADESK Studio。。。 Excel 插件为任何使用 Excel 执行数学、工程和科学计算的人提供了必备工具。 * 将公式视为真正的数学方程 * 为您的公…...

大规模 Spring Cloud 微服务无损上下线探索与实践

文章目录 什么是无损上下线&#xff1f;大规模 Spring Cloud 微服务架构实现无损上下线的挑战无损上下线的实践1. 使用负载均衡器2. 使用数据库迁移工具3. 动态配置管理4. 错误处理和回滚 未来的趋势1. 容器编排2. 服务网格3. 自动化测试和验证 结论 &#x1f389;欢迎来到云原…...

【LeetCode】剑指 Offer 54. 二叉搜索树的第k大节点

题目&#xff1a; 给定一棵二叉搜索树&#xff0c;请找出其中第 k 大的节点的值。 示例 1: 输入: root [3,1,4,null,2], k 13/ \1 4\2 输出: 4 示例 2: 输入: root [5,3,6,2,4,null,null,1], k 35/ \3 6/ \2 4/1 输出: 4 限制&#xff1a; 1 ≤ k ≤ 二叉搜索树…...

C++设计模式_03_模板方法Template Method

文章目录 1. 设计模式分类1.1 GOF-23 模式分类1.2 从封装变化角度对模式分类 2. 重构&#xff08;使用模式的方法&#xff09;2.1 重构获得模式 Refactoring to Patterns2.2 重构关键技法 3. “组件协作”模式4. Template Method 模式4.1 动机&#xff08; Motivation&#xff…...

【LeetCode-中等题】79. 单词搜索

文章目录 题目方法一&#xff1a;递归 回溯 题目 方法一&#xff1a;递归 回溯 需要一个标记数组 来标志格子字符是否被使用过了先找到word 的第一个字符在表格中的位置&#xff0c;再开始递归递归的结束条件是如果word递归到了最后一个字符了&#xff0c;说明能在矩阵中找到单…...

揭秘iPhone 15 Pro Max:苹果如何战胜三星

三星Galaxy S23 Ultra在我们的最佳拍照手机排行榜上名列前茅有几个原因&#xff0c;但iPhone 15 Pro Max正在努力夺回榜首——假设它有一个特定的功能。别误会我的意思&#xff0c;苹果一直在追赶三星&#xff0c;因为它的iPhone 14 Pro和14 Pro Max都表现强劲。尽管如此&#…...

分布式秒杀方案--java

前提&#xff1a;先把商品详情和秒杀商品缓存redis中&#xff0c;减少对数据库的访问&#xff08;可使用定时任务&#xff09; 秒杀商品无非就是那几步&#xff08;前面还可能会有一些判断&#xff0c;如用户是否登录&#xff0c;一人一单&#xff0c;秒杀时间验证等&#xff0…...

高频golang面试题:简单聊聊内存逃逸?

文章目录 问题怎么答举例 问题 知道golang的内存逃逸吗&#xff1f;什么情况下会发生内存逃逸&#xff1f; 怎么答 golang程序变量会携带有一组校验数据&#xff0c;用来证明它的整个生命周期是否在运行时完全可知。如果变量通过了这些校验&#xff0c;它就可以在栈上分配。…...

【2023年数学建模国赛C题解题思路】

第一问 要求分析分析蔬菜各品类及单品销售量的分布规律及相互关系。该问题可以拆分成三个角度进行剖析。 1&#xff09;各种类蔬菜的销售量分布、蔬菜种类与销售量之间的关系&#xff1b;2&#xff09;各种类蔬菜的销售量的月份分布、各种类蔬菜销售量与月份之间的相关关系&a…...

Jenkins+Allure+Pytest的持续集成

一、配置 allure 环境变量 1、下载 allure是一个命令行工具&#xff0c;可以去 github 下载最新版&#xff1a;https://github.com/allure-framework/allure2/releases 2、解压到本地 3、配置环境变量 复制路径如&#xff1a;F:\allure-2.13.7\bin 环境变量、Path、添加 F:\a…...

yo!这里是进程控制

目录 前言 进程创建 fork()函数 写时拷贝 进程终止 退出场景 退出方法 进程等待 等待原因 等待方法 1.wait函数 2.waitpid函数 等待结果&#xff08;status介绍&#xff09; 进程替换 替换原理 替换函数 进程替换例子 shell简易实现 后记 前言 学习完操作…...

多线程快速入门

线程与进程区别 每个正在系统上运行的程序都是一个进程。每个进程包含一到多个线程。线程是一组指令的集合&#xff0c;或者是程序的特殊段&#xff0c;它可以在程序里独立执行。也可以把它理解为代码运行的上下文。所以线程基本上是轻量级的进程&#xff0c;它负责在单个程序里…...

Redis 7 第七讲 哨兵模式(sentinal)架构篇

哨兵模式 哨兵巡查监控后台master主机是否故障,如果出现故障根据投票时自动将某一个从库转换成新的主库,继续对外服务。 作用 1. 监控redis运行状态,包括master和slave 2. 当master down机,能自动将salve切换成新的master 应用场景 主从监控监控主从redis库运行的状态…...

laravel框架系列(一),Dcat Admin 安装

介绍 Laravel 是一个流行的 PHP 开发框架&#xff0c;它提供了一套简洁、优雅的语法和丰富的功能&#xff0c;用于快速构建高质量的 Web 应用程序。 以下是 Laravel 的一些主要特点和功能&#xff1a; MVC 架构&#xff1a;Laravel 使用经典的模型-视图-控制器&#xff08;MV…...

Linux:工具(vim,gcc/g++,make/Makefile,yum,git,gdb)

目录 ---工具功能 1. vim 1.1 vim的模式 1.2 vim常见指令 2. gcc/g 2.1 预备知识 2.2 gcc的使用 3.make,Makefile make.Makefile的使用 4.yum --yum三板斧 5.git --git三板斧 --Linux下提交代码到远程仓库 6.gdb 6.1 gdb的常用指令 学习目标&#xff1a; 1.知道…...

小节1:Python字符串打印

1、字符串拼接 用可以将两个字符串拼接成一个字符串 print("你好 " "这是一串代码") 输出&#xff1a; 2、单双引号转义 当打印的字符串中带有引号或双引号时&#xff0c;使用\或\"表示 print("He said \"Let\s go!\"") 输…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

分布式增量爬虫实现方案

之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面&#xff0c;避免重复抓取&#xff0c;以节省资源和时间。 在分布式环境下&#xff0c;增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路&#xff1a;将增量判…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

快刀集(1): 一刀斩断视频片头广告

一刀流&#xff1a;用一个简单脚本&#xff0c;秒杀视频片头广告&#xff0c;还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农&#xff0c;平时写代码之余看看电影、补补片&#xff0c;是再正常不过的事。 电影嘛&#xff0c;要沉浸&#xff0c;…...

并发编程 - go版

1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...