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

wordpress自动发布文章疫情二十条优化措施

wordpress自动发布文章,疫情二十条优化措施,做网站需要学jq吗,怎么选择大连网站建设W...Y的主页 😊 代码仓库管理💕 前言:之前我们已经学习了TCP传输协议,而无论是TCP还是UDP都是使用socket套接字进行网络传输的,而TCP的socket是比UDP复杂的,当时我们学习TCPsocket编程时使用listen函数进行…

W...Y的主页 😊

代码仓库管理💕


前言:之前我们已经学习了TCP传输协议,而无论是TCP还是UDP都是使用socket套接字进行网络传输的,而TCP的socket是比UDP复杂的,当时我们学习TCPsocket编程时使用listen函数进行监听,今天我们就来说说listen函数第二个参数的含义,并且打通socket与内核之间的关系!!

目录

理解 listen 的第二个参数 

理解全连接队列

在内核中理解全连接队列与套接字


理解 listen 的第二个参数 

基于刚才封装的 TcpSocket 实现以下测试代码。对于服务器, listen 的第二个参数设置为 1, 并且不调用 accept。不调用accept就无法建立连接,导致这些连接全部会在全连接队列中(全连接队列是什么我们会在后面讲述)。

test_server.cc

#include "tcp_socket.hpp"
int main(int argc, char* argv[]) {
if (argc != 3) {
printf("Usage ./test_server [ip] [port]\n");
return 1;
}
TcpSocket sock;
bool ret = sock.Bind(argv[1], atoi(argv[2]));
if (!ret) {
return 1;
}
ret = sock.Listen(2);
if (!ret) {
return 1;
}
// 客户端不进行 accept
while (1) {
sleep(1);
}
return 0;
}

 test_client.cc

#include "tcp_socket.hpp"
int main(int argc, char* argv[]) {
if (argc != 3) {
printf("Usage ./test_client [ip] [port]\n");
return 1;
}
TcpSocket sock;
bool ret = sock.Connect(argv[1], atoi(argv[2]));
if (ret) {
printf("connect ok\n");
} else {
printf("connect failed\n");
}
while (1) {
sleep(1);
}
return 0;
}

此时启动 3 个客户端同时连接服务器, 用 netstat 查看服务器状态, 一切正常,但是启动第四个客户端时, 发现服务器对于第四个连接的状态存在问题了。

tcp 3 0 0.0.0.0:9090 0.0.0.0:*
LISTEN 9084/./test_server
tcp 0 0 127.0.0.1:9090 127.0.0.1:48178
SYN_RECV -
tcp 0 0 127.0.0.1:9090 127.0.0.1:48176
ESTABLISHED -
tcp 0 0 127.0.0.1:48178 127.0.0.1:9090
ESTABLISHED 9140/./test_client
tcp 0 0 127.0.0.1:48174 127.0.0.1:9090
ESTABLISHED 9087/./test_client
tcp 0 0 127.0.0.1:48176 127.0.0.1:9090
ESTABLISHED 9088/./test_client
tcp 0 0 127.0.0.1:48172 127.0.0.1:9090
ESTABLISHED 9086/./test_client
tcp 0 0 127.0.0.1:9090 127.0.0.1:48174
ESTABLISHED -
tcp 0 0 127.0.0.1:9090 127.0.0.1:48172
ESTABLISHED -

前三个连接状态都是established,而第四个连接的客户端的状态是syn_sent(链接同步发送状态)是没有连接成功的,三次握手都没有成功。往后所以的客户端想要连接都会是syn_sent状态。

所以我们得出结论:在服务器来不及accept时,底层的TCP listen socket允许用户进行三次握手建立成功连接,但是不能建立太多,最多能建立backlog + 1个连接。 而这个backlog就是listen函数的第二个参数。

我们将这些建立好连接的链接会放在一个队列来维护,这个队列就是全连接队列。

客户端状态正常, 但是服务器端出现了 SYN_RECV 状态, 而不是 ESTABLISHED 状态这是因为, Linux 内核协议栈为一个 tcp 连接管理使用两个队列:
1. 半链接队列(用来保存处于 SYN_SENT 和 SYN_RECV 状态的请求)
2. 全连接队列(accpetd 队列)(用来保存处于 established 状态,但是应用层没有调用 accept 取走的请求)
而全连接队列的长度会受到 listen 第二个参数的影响.
全连接队列满了的时候, 就无法继续让当前连接的状态进入 established 状态了.
这个队列的长度通过上述实验可知, 是 listen 的第二个参数 + 1.

理解全连接队列

连接本质是内核中的一种数据结构,而我们使用socket套接字中的accept就是为了将已经建立好的连接拿上来进行使用。accpet函数在建立连接的同时,还能获取客户端的地址和端口信息。

我们不能将backlog中参数和服务器只能处理backlog+1个连接所混淆,服务器可以处理多个请求,这些连接就会被拿到上层不再全连接队列中,而全连接队列中的连接是已经建立好三次握手连接的却来不及接收的连接!!! 

而我们不能不要这个全连接队列,因为这个全连接队列就相当于一个缓冲区,这个模式就是生产消费者模型,如果服务端突然空闲那就可以连接全连接队列中的连接,提高了整个服务端的吞吐量和用户的体验。如果没有全连接队列就会增加服务端的闲置率!

我们也不能设置太长,如果设置太长那么晚来的客户端就在队列的尾部也会等很长时间,许多用户等不住就会关掉连接,但是还没有达到最终目的浪费了用户时间并且浪费服务器维护队列空间。 

在内核中理解全连接队列与套接字

在Linux内核中,task_struct结构体是描述进程的核心数据结构,它包含了控制和管理进程所必需的全部信息。 而struct file_struct结构体是用啦维护文件描述符的一个数据结构,他记录了一个进程打开的所有文件消息,file_struct中有一个fd数组用来记录文件描述符的。

在Linux内核中,struct file 结构体代表一个打开的文件,系统中的每个打开的文件在内核空间都有一个关联的 struct file 实例。

所以使用listen_socket打开一个文件,就有一个文件描述符指向打开的struck file中,这时我们所理解的。

而我们使用socket创建套接字时,内核就为我们创建了一个struct socket结构体,struct file 与struct socket用*private_data指针关联,上图就是我们结构体的内容。struct socket结构体就是我们网络的入口。

但真实的情况是创建一个TCP连接,而真正的应该是一个tcp_sock的结构体。而tcp是面向连接的,里面有一个字段也是一个结构体是struct  inet_connection_sock,他说tcp_sock中第一个字段,这个结构体包含了tcp链接的相关消息(超时时间……),里面有个字段是struct request_sock_queue icsk_accept_queue,这个就是全连接队列。而struct  inet_connection_sock中第一个字段又是一个结构体struct inet_sock(里面有源端口、目的端口、源IP、目的IP……)而struct inet_sock里面第一个字段又是一个结构体struct sock

而我们的struct socket结构体中有一个字段struct sock* sk指针,这个指针就可以指向struct tcp_sock结构体并且使用强转就可以对tcp_sock里面的所有字段进行访问。这就是C风格的多态。

而我们的UDP与TCP大相径庭,只不过UDP是无连接的,所以在udp_sock中没有struct  inet_connection_sock字段,剩下都是一样的。

我们的struct socket中有一个字段struct proto_ops结构体指针,里面存放了UDP与TCP的函数方法集。所以我们的struct socket是基类,tcp_sock与udp_sock都是子类。我们把struct socket叫做BSD socket——通用socket接口,把子类叫做inet_sock 

上述是我们讲述的创建一个listen套接字,而如何获取一个连接呢(accept)?

当我们进行三次握手成功后就会建立tcp_sock结构体,这个结构体会被连入全连接队列中,后面我们进行accept时就会创建struct file 然后再创建struct socket,之后将struct file 与struct socket用*private_data指针关联起来并在文件描述符表中申请一个fd(这些操作都是由一个函数(映射)完成的(sock_map_fd)),然后就会再全连接队列中获取tcp_sock结构体进行关联,直接用struct socket中的sock指针指向tcp_sock结构体,这样我们的一个普通套接字也有上述对应的结构了。

这就是在内核中socket、UDP、TCP、全连接队列、文件所对应的关系,下面我们用一张非常简单的图来表示对应关系:

 

 


详细可以参考源码,此处不展示!!!

http://www.ds6.com.cn/news/45912.html

相关文章:

  • 响应式网站的排版重庆seo1
  • 做网站图片要求高吗长沙关键词优化推荐
  • 游戏网站制作模板网站代搭建维护
  • 企业做网站的拼多多seo搜索优化
  • 温州网站建设制作seo网站诊断价格
  • 聊城专业网站设计公司关键词优化方法有什么步骤
  • 网站建设动态页面修改删除竞价排名是按照什么来计费的
  • 比较好的微网站开发平台seo快速优化软件网站
  • 网站的文字被爬取了免费域名申请网站
  • 郑州 发布会seo初级入门教程
  • 分类网站怎么做项目免费数据分析网站
  • 网站注册商标网络引流怎么做啊?
  • 我想做个百度网站怎么做的深圳市社会组织总会
  • 网站首页焦点图女生读网络营销与电商直播
  • 湖州网站开发广州网页推广公司
  • 网站建设的新闻动态企业网站推广方法实验报告
  • 外贸在哪些网站开发客户网络推广渠道分类
  • 简单的企业网站环球贸易网
  • 中山网站制作建设合肥百度快速排名优化
  • 浏览器怎么连接网站的深圳优化seo排名
  • 移动端下拉框价威cj111602推广新乡seo顾问
  • 做网站首页应该考虑什么全达seo
  • 东莞关键词优化实力乐云seo2020 惠州seo服务
  • 小公司自己怎样做网站北京seo网络优化师
  • 网站制作过程seo批量建站
  • 晋城做网站bt鹦鹉磁力
  • 西安做网站推广优化服务公司
  • 安卓做视频网站好seo排名赚app是真的吗
  • 手机网站横幅制作模板基础建站如何提升和优化
  • 做网站赚钱嘛成都网多多