Socket层

news/2024/11/20 3:29:22/文章来源:https://www.cnblogs.com/ligo6/p/18197110

【一】什么是socket

  • Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。
    • 在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面
    • 对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
  • 所以,我们无需深入理解tcp/udp协议,socket已经为我们封装好了,我们只需要遵循socket的规定去编程,写出的程序自然就是遵循tcp/udp标准的。
  • 也有人将socket说成ip+port
    • ip是用来标识互联网中的一台主机的位置
    • 而port是用来标识这台机器上的一个应用程序
    • ip地址是配置到网卡上的
    • 而port是应用程序开启的
    • ip与port的绑定就标识了互联网中独一无二的一个应用程序
  • 而程序的pid是同一台机器上不同进程或者线程的标识

【二】套接字发展史及分类

  • 套接字起源于 20 世纪 70 年代加利福尼亚大学伯克利分校版本的 Unix,即人们所说的 BSD Unix。
  • 因此,有时人们也把套接字称为“伯克利套接字”或“BSD 套接字”。
  • 一开始,套接字被设计用在同 一台主机上多个应用程序之间的通讯。
  • 这也被称进程间通讯,或 IPC。套接字有两种,分别是基于文件型的和基于网络型的。

【1】基于文件类型的套接字家族

  • 套接字家族的名字:AF_UNIX
  • unix一切皆文件
    • 基于文件的套接字调用的就是底层的文件系统来取数据
    • 两个套接字进程运行在同一机器
    • 可以通过访问同一个文件系统间接完成通信

【2】基于网络类型的套接字家族

  • 套接字家族的名字:AF_INET
  • 还有AF_INET6被用于ipv6,还有一些其他的地址家族:
    • 所有地址家族中,AF_INET是使用最广泛的一个
    • python支持很多种地址家族,但是由于我们只关心网络编程,所以大部分时候我么只使用AF_INET

【三】套接字工作流程

  • 一个生活中的场景。
    • 你要打电话给一个朋友,先拨号,朋友听到电话铃声后提起电话,这时你和你的朋友就建立起了连接,就可以讲话了。等交流结束,挂断电话结束此次交谈。

【1】流程分析(文字)

  • 服务端:
    • 服务器端先初始化socket对象
    • 然后与本地端口绑定(bind),对端口进行监听(listen)
    • 调用accept阻塞,等待客户端连接
    • 服务端send发送数据请求,客户端接收请求并处理请求
    • 然后客户端把回应数据发送给服务端,服务端接收并读取数据
    • 最后关闭连接(close),一次交互结束
  • 客户端:
    • 客户端初始化一个socket对象
    • 然后与本地端口绑定(bind)
    • 然后连接服务器(connect)
    • 客户端接收并读取数据
    • 客户端send发送数据请求,服务器端接收请求并处理请求
    • 最后关闭连接(close),一次交互结束

【2】流程分析(代码)

  • 服务端
import socket# 【1】服务器端先初始化socket对象
# AF_INET:当前连接是基于网络的套接字
# SOCK_STREAM:连接模式是TCP协议的流式模式
server_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)# 【2】然后与本地端口绑定(bind),对端口进行监听(listen)
ip = '127.0.0.6'
port = 8080
server_socket.bind((ip, port))
# 半连接池
server_socket.listen()# 【3】调用accept阻塞,等待客户端连接
conn, addr = server_socket.accept()# 【4】服务端send发送数据请求,客户端接收请求并处理请求
# #只能发送二进制数据
data = ''
conn.send(data.encode())  # 编码二进制数据# 【5】然后客户端把回应数据发送给服务端,服务端接收并读取数据
data = conn.recv(1024)  # 1024个字节
print(data.decode())  # 解码二进制数据
# 最后关闭连接(close),一次交互结束
conn.close()
server_socket.close()
  • 客户端
import socket# 【1】客户端初始化一个Socket
client_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)# 【2】然后与本地端口绑定(bind),连接服务器(connect)
ip = '127.0.0.6'
port = 8080
client_socket.connect((ip, port))# 【3】客户端接收并读取数据
data = client_socket.recv(1024)
print(data.decode())
# 【4】客户端send发送数据请求,服务器端接收请求并处理请求
data = ''
client_socket.send(data.encode())
# 【6】最后关闭连接(close),一次交互结束
client_socket.close()

【3】套接字的相关函数

#【1】服务端套接字函数
s.bind() 绑定(主机,端口号)到套接字
s.listen() 开始TCP监听
s.accept() 被动接受TCP客户的连接,(阻塞式)等待连接的到来
#【2】客户端套接字函数
s.connect() 主动初始化TCP服务器连接
s.connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛出异常
#【3】公共用途的套接字函数
s.recv() 接收TCP数据
s.send() 发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完)
s.sendall() 发送完整的TCP数据(本质就是循环调用send,sendall在待发送数据量大于己端缓存区剩余空间时,数据不丢失,循环调用send直到发完)
s.recvfrom() 接收UDP数据
s.sendto() 发送UDP数据
s.getpeername() 连接到当前套接字的远端的地址
s.getsockname() 当前套接字的地址
s.getsockopt() 返回指定套接字的参数
s.setsockopt() 设置指定套接字的参数
s.close() 关闭套接字
#【4】面向锁的套接字方法
s.setblocking() 设置套接字的阻塞与非阻塞模式
s.settimeout() 设置阻塞套接字操作的超时时间
s.gettimeout() 得到阻塞套接字操作的超时时间
#【5】面向文件的套接字的函数
s.fileno() 套接字的文件描述符
s.makefile() 创建一个与该套接字相关的文件

【四】三次握手和四次挥手

# 【1】TCP协议的三次握手和四次挥手
# TCP协议位于osi七层协议中的传输层
# 使用三次握手来建立连接
# 使用四次挥手来断开连接
# 【2】常用名词
# SYN:SYN=1 表示要建立连接
# ACK:ACK=1 表示我收到了,允许
# seq:随机数,建立连接无论客户端还是服务端要建立连接就要要携带
# ack:回应请求就要加1返回
# FIN:表示断开连接

【1】三次握手

# 三次握手发生在建立连接的阶段
# 【1】第一次请求
# 由客户端发起请求 带SYN=1
# 表示我自己是客户端我要建立连接
# seq随机数带
# 发送给服务端
# 客户端 ---> 携带 SYN和SEQ ---> 发送给服务端
# 【2】第二次请求
# 服务端接收到客户端的请求
# ACK=1 表示收到了当前客户端发送给我的请求
# SYN=1 表示要建立连接
# seq:随机数
# 服务端 ---> 接收到客户端的请求,同意建立连接 ---> 发送给客户端
# 【3】第三次请求
# 客户端接收到了服务端的请求
# ACK=1 表示收到了当前服务端发送给我的请求
# SYN=1 表示要建立连接
# seq:随机数
# 和服务端建立连接成功

【2】四次挥手

# 四次挥手发生在断开连接上
# 【1】第一次
# 客户端向服务端发送请求,我想要断开连接
# 【2】第二次
# 服务端接收到客户端的请求
# 表示同意断开连接
# 【3】第三次
# 服务单向客户端发送请求,请求的原因是当前还有数据没有传输完成
# 请求等待,等待数据传输完成
# 发起请求,断开连接
# 服务端向客户端发送请求,请求断开连接
# 【4】第四次
# 客户端接收到服务端的请求
# 直接断开连接

【五】基于TCP的套接字

  • 服务端
import socket# 【1】服务器端先初始化socket对象
# AF_INET:当前连接是基于网络的套接字
# SOCK_STREAM:连接模式是TCP协议的流式模式
server_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)# 【2】然后与本地端口绑定(bind),对端口进行监听(listen)
ip = '127.0.0.7'
port = 8080
server_socket.bind((ip, port))
# 半连接池
server_socket.listen(5)# 【3】调用accept阻塞,等待客户端连接
conn, addr = server_socket.accept()# 【4】服务端send发送数据请求,客户端接收请求并处理请求
# #只能发送二进制数据
to_client_data = '我是来自服务端的数据'
conn.send(to_client_data.encode())  # 编码二进制数据# 【5】然后客户端把回应数据发送给服务端,服务端接收并读取数据
from_client_data = conn.recv(1024)  # 1024个字节
print(from_client_data.decode())  # 解码二进制数据
# 最后关闭连接(close),一次交互结束
conn.close()
server_socket.close()
  • 客户端
import socket# 【1】客户端初始化一个Socket
# AF_INET:当前连接是基于网络的套接字
# SOCK_STREAM:连接模式是TCP协议的流式模式
client_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)# 【2】然后与本地端口绑定(bind),连接服务器(connect)
ip = '127.0.0.7'
port = 8080
client_socket.connect((ip, port))# 【3】客户端接收并读取数据
from_server_data = client_socket.recv(1024)
print(from_server_data.decode())
# 【4】客户端send发送数据请求,服务器端接收请求并处理请求
to_server_data = '我是来自客户端的数据'
client_socket.send(to_server_data.encode())
# 【6】最后关闭连接(close),一次交互结束
client_socket.close()

【六】基于UDP的套接字

  • 服务端
from conf import settings
import socket# 【1】服务器端先初始化socket对象
# AF_INET:当前连接是基于网络的套接字
# SOCK_DGRAM:连接模式是UDP协议的报式模式
server_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)# 【2】然后与本地端口和ip绑定(bind)
server_socket.bind(settings.ADDR)# 【3】服务端接收并读取客户端数据
from_client_data, addr = server_socket.recvfrom(1024)  # 1024个字节
print(from_client_data.decode())  # 解码二进制数据
# 我是来自客户端的数据
print(f"addr;{addr}")
# addr;('127.0.0.1', 60561)# 【4】服务端返回给客户端数据
# #只能发送二进制数据
to_client_data = '我是来自服务端的数据'
server_socket.sendto(to_client_data.encode(), addr)  # 编码二进制数据
# 最后关闭连接(close)
server_socket.close()
  • 客户端
from conf import settings
import socket# 【1】客户端初始化一个socket对象
# AF_INET:当前连接是基于网络的套接字
# SOCK_DGRAM:连接模式是UDP协议的报式模式
client_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)# 【2】客户端直接向服务器端发送数据
to_server_data = '我是来自客户端的数据'
client_socket.sendto(to_server_data.encode(), settings.ADDR)
print(client_socket)
# <socket.socket fd=384, family=AddressFamily.AF_INET, type=SocketKind.SOCK_DGRAM, proto=0, laddr=('0.0.0.0', 60561)># 【3】客户端接收并读取服务端的数据
from_server_data, addr = client_socket.recvfrom(1024)
print(from_server_data.decode())
# 我是来自服务端的数据
print(f"addr:{addr}")
# addr:('127.0.0.7', 8080)# 【6】最后关闭连接(close)
client_socket.close()

【七】TCP协议模型

【1】一代

  • 服务端
from conf import settings
import socket# 【1】服务器端先初始化socket对象
# AF_INET:当前连接是基于网络的套接字
# SOCK_STREAM:连接模式是TCP协议的流式模式
server_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)# 【2】然后与本地端口和ip绑定(bind)
server_socket.bind(settings.ADDR)# 【3】监听连接对象
server_socket.listen(5)# 【4】连接客户端
conn, addr = server_socket.accept()
print(conn)
# <socket.socket fd=300, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.7', 8080), raddr=('127.0.0.1', 51175)># 【5】服务端接收并读取客户端数据
from_client_data = conn.recv(1024)  # 1024个字节
print(from_client_data.decode())  # 解码二进制数据
# 我是来自客户端的数据
print(f"addr;{addr}")
# addr;('127.0.0.1', 51175)# 【6】服务端返回给客户端数据
# #只能发送二进制数据
to_client_data = '我是来自服务端的数据'
conn.send(to_client_data.encode())  # 编码二进制数据
# 【7】最后关闭连接(close)
conn.close()
server_socket.close()
  • 客户端
import socket
from conf import settings# 【1】客户端初始化一个Socket
# AF_INET:当前连接是基于网络的套接字
# SOCK_STREAM:连接模式是TCP协议的流式模式
client_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)# 【2】连接服务器
client_socket.connect(settings.ADDR)# 【3】客户端直接向服务器端发送数据
to_server_data = '我是来自客户端的数据'
client_socket.send(to_server_data.encode())
print(client_socket)
# <socket.socket fd=392, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 51175), raddr=('127.0.0.7', 8080)># 【4】客户端接收并读取服务端的数据
from_server_data = client_socket.recv(1024)
print(from_server_data.decode())
# 我是来自服务端的数据# 【5】最后关闭连接(close)
client_socket.close()

【2】二代(只能发一次信息)

  • 服务端
from conf import settings
import socket# 【1】服务器端先初始化socket对象
# AF_INET:当前连接是基于网络的套接字
# SOCK_STREAM:连接模式是TCP协议的流式模式
server_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)# 【2】然后与本地端口和ip绑定(bind)
server_socket.bind(settings.ADDR)# 【3】监听连接对象
server_socket.listen(5)
while True:# 【4】连接客户端conn, addr = server_socket.accept()# 【5】服务端接收并读取客户端数据from_client_data = conn.recv(1024)  # 1024个字节print(f"这是来自客户端的数据;{from_client_data.decode()}")  # 解码二进制数据# 【6】服务端返回给客户端数据# #只能发送二进制数据to_client_data = input("请输入发送给客户端的数据:").strip()conn.send(to_client_data.encode())  # 编码二进制数据
# 【7】最后关闭连接(close)
conn.close()
server_socket.close()
  • 客户端
import socket
from conf import settings# 【1】客户端初始化一个Socket
# AF_INET:当前连接是基于网络的套接字
# SOCK_STREAM:连接模式是TCP协议的流式模式
client_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)# 【2】连接服务器
client_socket.connect(settings.ADDR)
while True:# 【3】客户端直接向服务器端发送数据to_server_data = input("请输入发送给服务端的数据:").strip()client_socket.send(to_server_data.encode())# 【4】客户端接收并读取服务端的数据from_server_data = client_socket.recv(1024)print(F"这是来自服务端的数据:{from_server_data.decode()}")# 我是来自服务端的数据# 【5】最后关闭连接(close)
client_socket.close()

【3】三代(可以多次发送信息)

  • 服务端
from conf import settings
import socket# 【1】服务器端先初始化socket对象
# AF_INET:当前连接是基于网络的套接字
# SOCK_STREAM:连接模式是TCP协议的流式模式
server_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)# 【2】然后与本地端口和ip绑定(bind)
server_socket.bind(settings.ADDR)# 【3】监听连接对象
server_socket.listen(5)# 【4】连接客户端
conn, addr = server_socket.accept()
while True:# 【5】服务端接收并读取客户端数据from_client_data = conn.recv(1024)  # 1024个字节print(f"这是来自客户端的数据;{from_client_data.decode()}")  # 解码二进制数据# 【6】服务端返回给客户端数据# #只能发送二进制数据to_client_data = input("请输入发送给客户端的数据:").strip()conn.send(to_client_data.encode())  # 编码二进制数据
# 【7】最后关闭连接(close)
conn.close()
server_socket.close()
  • 客户端
import socket
from conf import settings# 【1】客户端初始化一个Socket
# AF_INET:当前连接是基于网络的套接字
# SOCK_STREAM:连接模式是TCP协议的流式模式
client_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)# 【2】连接服务器
client_socket.connect(settings.ADDR)
while True:# 【3】客户端直接向服务器端发送数据to_server_data = input("请输入发送给服务端的数据:").strip()client_socket.send(to_server_data.encode())# 【4】客户端接收并读取服务端的数据from_server_data = client_socket.recv(1024)print(F"这是来自服务端的数据:{from_server_data.decode()}")# 我是来自服务端的数据# 【5】最后关闭连接(close)
client_socket.close()

【4】四代(断开连接,信息为空)

  • 服务端
from conf import settings
import socket# 【1】服务器端先初始化socket对象
# AF_INET:当前连接是基于网络的套接字
# SOCK_STREAM:连接模式是TCP协议的流式模式
server_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)# 【2】然后与本地端口和ip绑定(bind)
server_socket.bind(settings.ADDR)# 【3】监听连接对象
server_socket.listen(5)
# 【4】连接客户端
conn, addr = server_socket.accept()
while True:# 【5】服务端接收并读取客户端数据from_client_data = conn.recv(1024)  # 1024个字节print(f"这是来自客户端的数据;{from_client_data.decode()}")  # 解码二进制数据# 【6】服务端返回给客户端数据# #只能发送二进制数据to_client_data = input("请输入发送给客户端的数据:").strip()conn.send(to_client_data.encode())  # 编码二进制数据
# 【7】最后关闭连接(close)
conn.close()
server_socket.close()
  • 客户端
import socket
from conf import settings# 【1】客户端初始化一个Socket
# AF_INET:当前连接是基于网络的套接字
# SOCK_STREAM:连接模式是TCP协议的流式模式
client_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)# 【2】连接服务器
client_socket.connect(settings.ADDR)
while True:# 【3】客户端直接向服务器端发送数据to_server_data = input("请输入发送给服务端的数据:").strip()if not to_server_data:print("输入的数据不能为空!")continueif to_server_data == "q":print("当前连接已断开!")breakclient_socket.send(to_server_data.encode())# 【4】客户端接收并读取服务端的数据from_server_data = client_socket.recv(1024)print(F"这是来自服务端的数据:{from_server_data.decode()}")# 我是来自服务端的数据# 【5】最后关闭连接(close)
client_socket.close()

【5】五代(检测用户信息为空)

  • 服务端
from conf import settings
import socket# 【1】服务器端先初始化socket对象
# AF_INET:当前连接是基于网络的套接字
# SOCK_STREAM:连接模式是TCP协议的流式模式
server_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)
# 【2】然后与本地端口和ip绑定(bind)
server_socket.bind(settings.ADDR)# 【3】监听连接对象
server_socket.listen(5)
# 【4】连接客户端
conn, addr = server_socket.accept()
while True:try:# 【5】服务端接收并读取客户端数据from_client_data = conn.recv(1024)  # 1024个字节if not from_client_data:breakprint(f"这是来自客户端的数据;{from_client_data.decode()}")  # 解码二进制数据# 【6】服务端返回给客户端数据# #只能发送二进制数据while True:to_client_data = input("请输入发送给客户端的数据:").strip()if not to_client_data:print("输入的数据不能为空!")continueif to_client_data == "q":print("当前连接已断开!")conn.send(to_client_data.encode())  # 编码二进制数据breakexcept Exception as e:break
# 【7】最后关闭连接(close)
conn.close()
server_socket.close()
  • 客户端
import socket
from conf import settings# 【1】客户端初始化一个Socket
# AF_INET:当前连接是基于网络的套接字
# SOCK_STREAM:连接模式是TCP协议的流式模式
client_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)# 【2】连接服务器
client_socket.connect(settings.ADDR)
while True:# 【3】客户端直接向服务器端发送数据to_server_data = input("请输入发送给服务端的数据:").strip()if not to_server_data:print("输入的数据不能为空!")continueif to_server_data == "q":print("当前连接已断开!")breakclient_socket.send(to_server_data.encode())# 【4】客户端接收并读取服务端的数据from_server_data = client_socket.recv(1024)if from_server_data == 'q':breakprint(F"这是来自服务端的数据:{from_server_data.decode()}")# 我是来自服务端的数据# 【5】最后关闭连接(close)
client_socket.close()

【八】UDP协议模型

  • UDP协议 -----> 数据报协议

【1】空数据的处理

  • TCP协议是水流式协议:传入的数据不能为空,因为水是一直流的,在传输过程中不会对数据进行操作
  • UDP协议是数据报协议:传入的数据可为空,在传输过程中UDP会对数据进行内部的拼接和处理

【2】断开链接的影响

  • TCP协议是水流式协议:在建立链接过程中,服务端和客户端的链接是一直存在的,断开一方都会对另一方造成影响
  • UDP协议是数据报协议:在建立链接过程中,是通过解析对方数据中的ip和端口,再向另一方返回数据的,所以一方发生问题并不会影响到另一方

【3】代码实现

  • 服务端
from conf import settings
import socket# 【1】服务器端先初始化socket对象
# 数据报协议  ------>  UDP 协议
# AF_INET:当前连接是基于网络的套接字
# SOCK_DGRAM:连接模式是UDP协议的报式模式
server_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
# 【2】然后与本地端口和ip绑定(bind)
server_socket.bind(settings.ADDR)
# 【3】服务端接收并读取客户端数据
from_client_data, addr = server_socket.recvfrom(1024)  # 1024个字节
print(f'来自客户端的消息:{from_client_data.decode()}')  # 解码二进制数据
# 我是来自客户端的数据
print(f"addr;{addr}")
# addr;('127.0.0.1', 60561)while True:# 【4】服务端返回给客户端数据# #只能发送二进制数据to_client_data = input('请输入消息:')server_socket.sendto(to_client_data.encode(), addr)  # 编码二进制数据
# 最后关闭连接(close)
server_socket.close()
  • 客户端
from conf import settings
import socket# 【1】客户端初始化一个socket对象
client_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
while True:# 【2】客户端直接向服务器端发送数据to_client_data = input("请输入消息:")client_socket.sendto(to_client_data.encode(), settings.ADDR)# 【3】客户端接收并读取服务端的数据from_server_data, addr = client_socket.recvfrom(1024)print(f'来自服务端的消息:{from_server_data.decode()}')print(f"addr:{addr}")# addr:('127.0.0.7', 8080)# 【6】最后关闭连接(close)
client_socket.close()

【九】端口冲突问题

【1】问题所在

  • 有时候重启服务端后会出现报错:[Errno 48] Address already in use
  • 这个是由于你的服务端仍然存在四次挥手的time_wait状态在占用地址

【2】解决办法

(1)方法一

#加入一条socket配置,重用ip和端口socket = socket(AF_INET,SOCK_STREAM)
socket.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #在bind前加
socket.bind(('127.0.0.1',8080))

(2)方法二

  • 发现系统存在大量TIME_WAIT状态的连接,通过调整linux内核参数解决
vi /etc/sysctl.conf
  • 编辑文件,加入以下内容
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
  • 参数说明
net.ipv4.tcp_syncookies = 1 
# 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1 
# 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1 
# 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
net.ipv4.tcp_fin_timeout 
# 修改系統默认的 TIMEOUT 时间
  • 然后执行 /sbin/sysctl -p 让参数生效。
/sbin/sysctl -p

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/707610.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

金融系统数据同步方案哪家最强,了解一下!

金融系统数据同步是金融行业信息化和数据化发展的关键组成部分,它对于保障数据安全、提升系统性能和满足日益增长的数据时效性要求至关重要。以下是一些金融系统中数据同步的关键应用场景和需求:1、多数据中心操作:金融机构通常在多个数据中心运行,需要确保数据在这些中心之…

Dapr 与 .NET Aspire 结合使用获得无与伦比的本地开发体验

Dapr 提供了一组构建块,用于抽象分布式系统中常用的概念。这包括服务、缓存、工作流、复原能力、机密管理等之间的安全同步和异步通信。不必自己实现这些功能,可以消除样板,降低复杂性,并允许您专注于开发业务功能。在您的时间有限并且您只想进行实验的情况下,在Dapr初始设…

网络架构和网络通信

【一】常见的网络架构模式 【1】CS模型C是英文单词“Client”的首字母,即客户端的意思 C/S就是“Client/Server”的缩写,即“客户端/服务器”模式。例如:拼多多APP、PC上的有道云笔记等等【2】BS模型B是英文单词“Browser”的首字母,即浏览器的意思; S是英文单词“Server”…

记录仪测评 记录仪测评设置4k结果1080

设置4K 实际效果1080不到记录仪测评设置4k结果1080 https://baijiahao.baidu.com/builder/preview/s?id=1799258600924107729 LOK00018.AVI音频编码信息ID : 1格式 : PCM格式参数设置, Endianness : Little格式参数设置, Sign : Signed编解码器ID : 1编解码器ID/Hint : Micros…

mpdf增加字体并进行使用

1、先将字体复制到目录:\vendor\mpdf\mpdf\ttfonts2、再修改文件\vendor\mpdf\mpdf\src\Config\FontVariables.php,对照已经添加的simsun,simkai,simhei,fangzhenweibei,fangzhenheiti等字体进行增加即可。3、再在需要设置字体的文字加上font-family:fangzhenweibei;样式…

初识上位机(下):C#读写PLC数据块数据

作为一个工业自动化领域的程序员,不懂点PLC和上位机,貌似有点说不过去。这里我用两篇小文带你快速进入上位机开发领域。上一篇,我们搭建了一个PLC的模拟仿真环境,本篇我们使用C#开发一个简单的PLC数据读取和写入的应用程序。大家好,我是Edison。 作为一个工业自动化领域的…

Markdown Editor 好用的工具

必要要记录一下,下次好找到。 Office Viewer(Markdown Editor) 好用的工具。 很适合我的。

linux开发和部署lazarus中间件

linux开发和部署lazarus中间件linux开发和部署lazarus中间件 1)linux开发的编译中间件2)linux部署中间件 本文来自博客园,作者:{咏南中间件},转载请注明原文链接:https://www.cnblogs.com/hnxxcxg/p/18197098

dotnet 设置 X11 建立窗口之间的父子关系

在 X11 里面有和 Win32 类似的窗口之间的关系机制,如 Owner-Owned 关系,以及 Parent-Child 关系。本文将告诉大家如何进行设置以及其行为本文将大量使用到 new bing 提供的回答内容,感谢 new bing 人工智能提供的内容 Owner-Owned 关系在这种关系中,一个窗口可以被另一个窗…

学习 Avalonia 框架笔记 设置 X11 窗口从最小化状态还原为正常状态

本文记录在 dotnet 里面如何设置 X11 窗口从最小化状态还原为正常状态本文属于学习 Avalonia 框架系列笔记,更多请参阅 博客导航 核心设置方法如下 /// <summary> /// 代码从 Avalonia 抄的 https://github.com/AvaloniaUI/Avalonia/blob/5e323b8fb1e2ca36550ca6fe678e4…

[转帖]全网最硬核 JVM 内存解析 - 4.Java 堆内存大小的确认

https://cloud.tencent.com/developer/article/2277323 个人创作公约:本人声明创作的所有文章皆为自己原创,如果有参考任何文章的地方,会标注出来,如果有疏漏,欢迎大家批判。如果大家发现网上有抄袭本文章的,欢迎举报,并且积极向这个 github 仓库 提交 issue,谢谢支持~…

[转帖]System Performance 读书笔记 - 操作系统(1)

https://cloud.tencent.com/developer/article/1927381 本系列是针对 Systems Performance: Enterprise and the Cloud, 2nd Edition (2020) 书籍的读书笔记,加入了一些个人理解以及拓展,并且针对一些难以理解的地方提供了一些额外的参考内核(Kernel) 经典模型中,内核在操…