【Python】UDP/TCP

Data Encoding and Decoding

utf-8 : Decoding of letters and English

GBK : Transcoding format for Chinese

str -> bytes: encode encoding, use encode encoding when sending information

bytes -> str: decode , print the received information and decode it with decode

test = '你好 世界'

en_code1 = test.encode('utf-8')
en_code2 = test.encode('gbk')

print(en_code1)
print(en_code2)
print(en_code1.decode('utf-8'))
print(en_code2.decode('gbk'))

socket

  • Socket, referred to as socket, is a tool for inter-process communication, and can also complete inter-process communication between different computers

  • First find the corresponding computer in the network through the ip address, then determine the process through the transmission protocol and port number, and use socket to complete inter-process communication, that is, data transmission

UDP

Connectionless-oriented : the sender can send data at any time without the existence of the peer

Features : no connection, low resource overhead, fast transmission speed, the maximum size of each data packet is 64k, suitable for broadcast applications

Defect : Unreliable data transmission, easy to lose packets; no flow control, the receiver needs to receive the data in time, otherwise the buffer will be full

UDP network process

  1. Ensure the normal startup of the UPD server, enter the recvfrom() mode, block and wait until the client sends data

  1. Open the UDP client, calibrate the IP address, and send data through the sendto() module

  1. When the server receives the data sent by the client, it processes the data and sends the response data to the client

  1. After receiving the response data, the client can process the data or send the data repeatedly, or exit the process

serve server

#coding=utf-8

from socket import *

# 1. 创建套接字
udp_socket = socket(AF_INET, SOCK_DGRAM)

# 2. 绑定本地的相关信息,如果一个网络程序不绑定,系统会随机分配
#    ip地址和端口号,如果不指明ip,则表示本机的任何一个ip
#    如果不指明端口号,则每次启动都是随机生成端口号
local_addr = ('', 12345)
udp_socket.bind(local_addr)

while True:
    # 3. 阻塞等待接收对方发送的信息
    #    1024表示本次接收的最大字节数
    recv_data = udp_socket.recvfrom(1024)

    # 4. 显示接收到的数据,并解码为gbk
    print(recv_data)
    print(recv_data[0].decode('utf-8'))
    
    # 5. 发送应答信息
    # ip_addr = recv_data[1][0]
    # port = recv_data[1][1]
    addr = recv_data[1]
    data = '信息已收到'
    udp_socket.sendto(data.encode('utf-8'), addr)


udp_socket.close()

clientclient

import socket

# 1. 创建upd套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 2. 准备服务端地址与端口号
#   127.0.0.1 代表自身ip地址,可向自身发送信息,也可指定ip地址发送信息
#   端口号随便填写一个未被占用的端口即可
#   Linux环境有65535个端口号,前1024个端口号是系统端口号,系统端口号不能直接使用
addr = ('127.0.0.1', 12345)

while True:
    # 3. 从键盘获取数据
    data = input('请输入信息:')

    # 4. 通过sendto()发送信息到指定进程中
    udp_socket.sendto(data.encode('utf-8'), addr)
    
    # 5. 通过recvfrom()阻塞等待获取应答数据
    recv_data = udp_socket.recvfrom(1024)
    
    # 6. 处理应答数据,进行打印
    print(recv_data)
    print(recv_data[0].decode('utf-8'))
    
    
udp_socket.close()

Running result: run the server first, then run the client

TCP

Connection-oriented : the two parties first establish a connection before data transmission

Features :

  • Both parties must allocate system kernel resources for the connection

  • After completing the data exchange, both parties must disconnect to release system resources

  • This connection is one-to-one and not suitable for broadcast applications

  • TCP提供可靠的数据传输,无差别、不丢失、不重复,且按序到达

  • 相比于UPD,TCP数据传输速度慢、对系统资源要求较高

  • TCP适合发送大量数据,UDP适合发送少量数据

  • TCP有流量控制,UPD无流量控制

TCP网络流程

serve服务端

from socket import *

# 1. 创建tcp套接字
tcp_serve_socket = socket(AF_INET, SOCK_STREAM)

# 2. 设置socket选项,程序退出后,端口会自动释放
tcp_serve_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, True)

# 3. 本地信息
addr = ('', 12345)

# 4. 绑定地址
tcp_serve_socket.bind(addr)

# 5. 设置监听
#    使用socket创建的套接字默认的属性是主动的,使用listen将其变为被动的
#    参数代表等待连接时间最多60秒
tcp_serve_socket.listen(60)

# 6. 如果有新的客户端来连接服务,就产生一个新的套接字,专门为这个客户端服务
#    client_socket用来为这个客户端服务
#    原来的tcp_serve_socket就可以专门用来等待其他新用户的连接
client_socket, client_addr = tcp_serve_socket.accept()

# 7. 阻塞等待客户端发送的信息
recv_data = client_socket.recv(1024)
print("接收到信息:", recv_data.decode('gbk'))

# 8. 发送应答信息
string = '已收到信息'
client_socket.send(string.encode('gbk'))

client_socket.close()

client客户端

import socket

# 1. 创建TCP的套接字
tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 2. 目标ip信息
ip = input('请输入服务端ip:')
port = int(input('请输入服务端port:'))

# 3. 连接服务器
tcp_client_socket.connect((ip, port))

# 4. 提示用户输入数据
data = input('请输入要发送的信息:')

# 5. 编码
tcp_client_socket.send(data.encode('gbk'))

# 6. 接收服务端的应答数据
recv_data = tcp_client_socket.recv(1024)
print('收到应答数据:', recv_data.decode('gbk'))

# 7. 关闭套接字
tcp_client_socket.close()

运行结果

如果忘记设置端口的关闭,非正常退出会导致端口一直被占用

linux环境在终端执行 ps aux | grep py 查看运行的进程,然后 kill -9 pid 杀掉进程

建立连接(三次握手)

SYN:连接请求 ACK:确认 FIN:关闭连接 seq:报文信号 ack:确认信号

  1. 第一次握手:client标志位SYN置1,随机产生一个seq=J,并将该数据包发送给serve,client进入SYN_SENT状态,等待serve确认

  1. 第二次握手:serve收到数据包后由标志位SYN=1知道client请求建立连接,serve将SYN和ACK都置1,ack(number)=J+1,+1是逻辑加一(加密),随机产生一个值seq=K,并将该数据包发送给client以确认连接请求,serve进入SYN_RECV状态

  1. 第三次握手:client收到确认,检查ack是否为J+1(解密),如果正确则将标志位ACK置1,ack=K+1,并将该数据包发送给serve,serve检查ack是否为K+1,如果正确则建立连接成功,client和serve同时进入ESTABLISHED状态,完成三次握手,随后client和serve之间可以传输数据

断开连接(四次挥手)

  1. 第一次挥手:client发送一个FIN,用来关闭client到serve的数据传送

  1. 第二次挥手:serve收到FIN后,发送一个ACK给client,确认序号为收到序号+1,表示还有剩余数据未传送完

  1. 第三次挥手:serve发送一个FIN,用来关闭serve到client的数据传送

  1. 第四次挥手:client收到FIN后,接着发送一个ACK给serve,确认序号为收到信号+1

Guess you like

Origin blog.csdn.net/phoenixFlyzzz/article/details/129790340