0
点赞
收藏
分享

微信扫一扫

tcp 三次握手,四次挥手

三次握手:

在用 tcp 传输数据时,需要先建立连接,用三次握手建立传输数据的连接通道

其实是服务端端和客户端各自都在准备资源。

  • 第一次握手:客户端向服务器发送连接请求包,标志位 SYN (同步序号)置为 seq = X;
  • 第二次握手:服务器收到客户端发过来的报文,由 SYN = X 知道客户端要求建立联机,向客户端发送一个包含 SYN 和 ACK 的 TCP 报文,其中服务器向客户端发送连接请求包,标志位 SYN (同步序列)置为 Y=1;将确认序号(ACK)设置为客户的序列号加 1,即 X + 1
  • 第三次握手:客户端收到服务器发来的包后检查确认序号(ACK)是否正确,即第一次发送的序号加1(X+1);若正确,服务器再次打算确认序号(ACK) = Y+1;服务器收到确认序号值 ACK=2 则连接成功,可以传送数据了。

四次挥手:

  • 第一次挥手:客户端给服务器发送 TCP 包,用来关闭客户端到服务器的数据传送,将标志位 FIN 置为 X 和 ACK 置为 Y ;
  • 第二次挥手:服务器收到 FIN 后,返回一个 ACK(标志位ACK=1)确认序号为收到的序号加1,即 X+1
  • 第三次挥手:服务器关闭与客户端的连接,发送一个 FIN,标志位 FIN和 ACK 置为1,序号为 Y
  • 第四次挥手:客户端收到服务器发送的 FIN 之后,发回 ACK 确认,确认序号为收到的序号加1,即Y+1,服务器手机 ACK 为 Y+1 后关闭

在第二次和第三次、第三次和第四次之间会有超时等待。

tcp 三次握手,四次挥手_服务器

"""
一个简单的http服务器
创建http服务器, tcp
"""
import socket
import re


def service_client(client_socket):
"""实现接收消息和发送消息"""
# 接收客户发送过来的请求
request = client_socket.recv(1024).decode("utf-8")
print(">>>" * 20)
print(request)

# 将客户端的请求变成列表
request_lines = request.splitlines()
print(request_lines)

# 使用正则取出客户端请求的数据名称
# request_lines = ['GET /images/trolltech-logo.png HTTP/1.1', 'Host: 127.0.0.1:8888']
# 从中取出 /images/trolltech-logo.png
ret = re.match(r"[^/]+(/[^ ]*) HTTP/1.1", request_lines[0])
client_request = ""
if ret:
print("客户端请求的数据是 %s" % ret.group(1))
client_request = ret.group(1)
if client_request == "/":
client_request = "/index.html"

try:
f = open("./html%s" % client_request, "rb")
except:
response_status_line = "HTTP/1.1 404 NOT FOUNT\r\n"
space_line = "\r\n"
response_header = response_status_line + space_line
response_body = "<h1>FILE NOT FOUND</h1>".encode("utf-8")
else:
html_content = f.read()
f.close()

# 根据客户需求回送数据过去
response_status_line = "HTTP/1.1 200 OK\r\n" # response status line 响应状态行 HTTP 必须大写 换行是\r\n
space_line = "\r\n" # 响应头和响应的数据之间有个空行
response_body = html_content # 发送的内容
response_header = response_status_line + space_line

client_socket.send(response_header.encode("utf-8")) # 注意:响应头是str格式,需要编码
client_socket.send(response_body) # 响应的内容需要是字节模式,不需要进行编码发送,浏览器会自动解析
# 关闭这个套接字
client_socket.close()


def main():
# 创建服务器的套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 可以让端口重复使用

# 绑定本地信息
tcp_server_socket.bind(("", 8888)) # 地址信息放在元组中

# 将套接字变为监听
tcp_server_socket.listen() # 最大的客户端链接数为128

while True:
# 等待客户端链接
# 如果有客户端链接,会返回元组,第一个元素是一个新的套接字专为这个客户端服务,第二个元素是客户端地址信息
new_socket, client_addr = tcp_server_socket.accept()

# 循环和客户的进行通信
service_client(new_socket)

# 关闭监听套接字
tcp_server_socket.close()


if __name__ == '__main__':
main()


举报

相关推荐

0 条评论