Python Notes 02 (Network Interaction TCP/UDP)

An introduction to socket network and differences

TCP (Transmission Control Protocol) and UDP (User Datagram Protocol) are two common Internet transmission protocols . There are many differences between them, including the following main aspects:

1.1 TCP

TCP is a transmission control protocol. It is a connection-oriented communication protocol (such as making a phone call). A connection is established through a three-way handshake , and four waves are waved when the communication is completed. It is generally used in scenarios that have strict requirements on security and integrity, such as FTP, SMTP, HTTP, etc.

  1. Advantages: TCP has high reliability , ensuring the accuracy of transmitted data without loss or disorder.
  2. Disadvantages: TCP is slower and less efficient than UDP , and requires more system resources. Each connection will occupy the system's CPU, memory and other hardware resources.

1.2 UDP

UDP is User Datagram Protocol, which is a connectionless communication protocol (such as sending text messages)

  1. Advantages: UDP is fast , easy to operate, and requires less system resources
  2. Disadvantages: Unreliable, packet loss , disorder, and incomplete data may occur

1.3 The difference between TCP and UDP:

  1. Connection TCP is a connection-oriented transport layer protocol. A connection must be established before data can be transmitted . UDP does not require a connection and transmits data immediately.
  2. The service object TCP is a one-to- one two-point service, that is, a connection has only two endpoints. UDP supports one-to-one, one-to-many , and many-to-many interactive communication
  3. Reliability TCP delivers data reliably , and the data can arrive in order without errors, loss, or duplication. UDP is a best effort delivery and does not guarantee reliable delivery of data.
  4. Congestion control and flow control TCP has congestion control and flow control mechanisms to ensure the security of data transmission. UDP does not. Even if the network is very congested, it will not affect the sending rate of UDP .
  5. Header Overhead The TCP header is long and will have a certain overhead. The header is 20 bytes when the "option" field is not used. If the "option" field is used, the header will become longer. The UDP header is only 8 bytes and is fixed , with less overhead and less system resource requirements.
  6. Real-time performance UDP has better real-time performance and higher working efficiency than TCP protocol.

1.4 Application scenarios

  1. Since TCP is connection-oriented and can ensure the reliable delivery of data, it is often used for: (20/21 port) FTP file transfer , HTTP / HTTPS (80 port), SMTP (Simple Mail Transfer Protocol), TELNET (Remote Terminal Protocol) )
  2. Because UDP is connectionless, it can send data at any time, and the processing of UDP itself is simple and efficient, so it is often used for: communications with a small total number of packets, such as DNS, SNMP, TFTP (Trivial File Transfer Protocol), etc. , video, audio and other multimedia communications, broadcast communications

1.5 Socket data transmission method

There are two commonly used ones:

  1. SOCK_STREAM : Represents connection-oriented data transmission method. Data can reach another computer without error, and if it is damaged or lost, it can be resent, but the efficiency is relatively slow. The common http protocol uses SOCK_STREAM to transmit data, because the correctness of the data must be ensured, otherwise the web page cannot be parsed normally. For connection-oriented TCP service applications;
  2. SOCK_DGRAM : Indicates connectionless data transmission method. The computer only transmits data and does not perform data verification. If the data is damaged during transmission or does not reach another computer, there is no way to remedy it. In other words, if the data is wrong, it is wrong and cannot be retransmitted. Because SOCK_DGRAM does less verification work, it is more efficient than SOCK_STREAM. Corresponds to connectionless UDP service applications.

1.6 Server side

from socket import *
server = socket(AF_INET, SOCK_DGRAM)
server_host_port = ('127.0.0.1', 6000)   # 服务器的IP地址和端口

# 接收数据前绑定端口
server.bind(server_host_port)

while True:
    # 接收数据
    data = server.recvfrom(1024)

    # print('data:', data)  # (b'\xe4\xbd\xa0\xe5\xa5\xbd', ('127.0.0.1', 61328))
    print('访问者:', data[0].decode('utf-8'))  # 你好
    # print(f'客户端的IP:{data[1][0]}  \n客户端的端口:{data[1][1]}')

    """重新发送数据"""
    send_data = input('客服说:')
    server.sendto(send_data.encode('utf-8'), data[1])

# server.close()

1.7 Client

from socket import *
client = socket(AF_INET, SOCK_DGRAM)
server_host_port = ('127.0.0.1', 6000)   # 指定数据接收方

while True:
    data = input('访问者:')
    data = data.encode('utf-8')
    client.sendto(data, server_host_port)   # 发送数据

    if data.decode('utf-8') == 'bye':
        break

    """接收返回数据数据"""
    recv_data = client.recvfrom(1024)
    print(f"客服说:{recv_data[0].decode('utf-8')}")

print('程序关闭')
client.close()

2 UDP protocol

Interactive use of udp: sendto and recvfrom

SOCK_DGRAM : Indicates connectionless data transmission method. The computer only transmits data and does not perform data verification. If the data is damaged during transmission or does not reach another computer, there is no way to remedy it. In other words, if the data is wrong, it is wrong and cannot be retransmitted. Because SOCK_DGRAM does less verification work, it is more efficient than SOCK_STREAM. Corresponds to connectionless UDP service applications.

2.1 Server code

from socket import *
import struct
server_socket = socket(AF_INET, SOCK_DGRAM)

host_port = ('localhost', 8888)   # 端口号

# 开始监听
server_socket.bind(host_port)

# 接收数据
data = server_socket.recvfrom(1024)
print(data, type(data))

# 解析操作码
recv_data = data[0]
new_data = struct.unpack('!H', recv_data[:2])
print('客户端请求的操作码:', new_data)

# 解析文件名
file_name = recv_data[2:-7].decode('utf-8')
print('客户端请求下载的文件名:', file_name)
server_socket.close()

2.2 Client code

from socket import *
import struct
client_socket = socket(AF_INET, SOCK_DGRAM)

host_port = ('localhost', 8888)   # 端口号

file_name = input('请输入需要上传的文件名:').encode('utf-8')
print('file_name:', file_name, len(file_name))
data = struct.pack('!H%dsb5sb' % len(file_name), 1, file_name, 0, 'octet'.encode('utf-8'), 0)

# 发送数据
client_socket.sendto(data, host_port)
client_socket.close()

Three TCP protocols

Interactive use of tcp: send and recv

SOCK_STREAM : Represents connection-oriented data transmission method. Data can reach another computer without error, and if it is damaged or lost, it can be resent, but the efficiency is relatively slow. The common http protocol uses SOCK_STREAM to transmit data, because the correctness of the data must be ensured, otherwise the web page cannot be parsed normally. For connection-oriented TCP service applications;

3.1 TCP server code

from socket import *
import random

# 创建SOCKET对象
server_socket = socket(AF_INET, SOCK_STREAM)

# 绑定IP和端口
host_port = ('', 6666)   # 不写本机所有
server_socket.bind(host_port)

# 设置listen
server_socket.listen(5)

while True:
    # 等待客户端连接
    client_socket, addr = server_socket.accept()
    print('客户端已连接,3次握手完成! ')
    # print('client_socket:', client_socket)

    # 接收数据
    data = client_socket.recv(1024).decode('utf8')
    print('data:', data)

    oper_code = data.split(':')[0]  # 操作码
    recv_data = data.split(':')[1]  # 需要上传和下载的文件

    if oper_code == '1':  # 下载操作
        file_read = open(recv_data, 'r', encoding='utf8')
        data = file_read.read()
        # 将数据发给客户端
        client_socket.send(data.encode('utf-8'))
        file_read.close()

    elif oper_code == '2':  # 上传操作
        file_write = open(str(random.randint(1000, 9999)) + '.txt', 'w', encoding='utf-8')
        file_write.write(recv_data)
        file_write.close()
        print('服务器接收完成!')

    elif oper_code == '0':  # 已退出
        print(recv_data)

3.2 Client code

from socket import *

while True:
    client_socket = socket(AF_INET, SOCK_STREAM)

    # 指定要连接的IP
    host_port = ('127.0.0.1', 6666)

    # 开始连接服务器
    client_socket.connect(host_port)

    choice = eval(input('请选择操作: 0.退出  1.下载  2.上传  \n'))

    if choice == 1:
        file_name = input('请输入要下载的文件名:')
        # 告诉服务器要下载的文件名
        join_data = (str(choice) + ':' + file_name).encode('utf-8')
        # 发送数据
        client_socket.send(join_data)

        # 接收服务器返回的数据
        recv_data = client_socket.recv(1024).decode('utf-8')
        # 写入本地磁盘
        download = open(file_name, 'w', encoding='utf-8')
        download.write(recv_data)
        download.close()
        print('下载完成')

    elif choice == 2:  # 上传
        path_name = input('请输入要上传的文件名:')
        # 本地读取
        upload = open(path_name, 'r', encoding='utf-8')
        upload_data = upload.read()

        # 拼接数据结构
        data = (str(choice) + ':' + upload_data).encode('utf-8')
        # 向服务器发送数据
        client_socket.send(data)
        upload.close()
        print('数据上传成功!')

    elif choice == 0:
        # 告诉服务器已退出
        client_socket.send((str(choice) + ':' + '客户端已退出').encode('utf-8'))
        break

print('客户端关闭')

Three-way handshake during TCP connection :

  • The first time: the client sends a connection message (SYN=1) to the server, and selects an initial sequence number seq=x and sends it together.

  • The second time: After receiving the message, the server sends a message to the client. The confirmation message is: (ACK=1, SYN=1), the confirmation number is ack=x+1, and the server initializes a sequence number: seq= y, send together

  • The third time: the client sends a message (ACK=1) to the server, and at the same time sends: ack=x+1, seq=y+1 for confirmation

Wave four times when TCP is disconnected : Wave four times when it is on:

  • The first time: the client sends a release message and stops sending data (FIN=1), with the sequence number seq=u, the client enters the termination waiting state (FIN-WAIT-1)

  • The second time: After receiving the message, the server releases the message, sends a confirmation message (ACK=1, ack=u+1), and carries the sequence number seq=v, and the server enters the shutdown waiting state (CLOSE-WAIT)

  • The third time: After the data transmission is completed, the server sends a connection release message (FIN=1, ack=u+1), and at the same time sends the sequence number: seq=w, and the server enters the final confirmation state (LAST-ACK)

  • The fourth time: After receiving the release message, the client sends a message (ACK=1, ack=w+1) to the server, sends the sequence number seq=u+1, and the client enters the time waiting state (TIME-WAIT) . The server closes directly after receiving the message, and the client needs to wait for 2**MSL (the longest message segment life) to end.

4. Use TCP to transfer larger files

4.1 Server-side code

from socket import *
import struct
server_socket = socket(AF_INET, SOCK_STREAM)  # TCP

host_port = ('', 6666)
server_socket.bind(host_port)

server_socket.listen(1024)
# 开始监听
conn_socket, addr = server_socket.accept()
print('查看服务器接收到的请求地址:', addr)

# 接收数据
data_header = conn_socket.recv(4)
# 解包
size = struct.unpack('!i', data_header)[0]
print('size:', size)

# 将收到的数据上传到磁盘
file = open('a.pptx', 'wb')
recv_size = 0
while recv_size < size:
    data_pack = conn_socket.recv(1024)
    recv_size += len(data_pack)

    file.write(data_pack)

file.close()
print('服务器接收完成')
conn_socket.close()
server_socket.close()

4.2 Client code

from socket import *
import os.path
import struct

client_socket = socket(AF_INET, SOCK_STREAM)
client_socket.connect(('192.168.146.1', 6666))

# 发送内容
file_path = './111.pptx'

# 获取文件大小
size = os.path.getsize(file_path)
print('size:', size)

# 对struct数据进行打包
data = struct.pack('!i', size)
# 发送数据
client_socket.send(data)

file = open(file_path, 'rb')
# 循环读取 1024
while True:
    data_pack = file.read(1024)
    if not data_pack:
        break
    client_socket.send(data_pack)   # 直接发

client_socket.close()

Guess you like

Origin blog.csdn.net/March_A/article/details/133254296