MST

星途 面试题库

面试题:Python网络编程自定义协议实现

设计并实现一个简单的基于TCP的自定义网络协议。该协议需要能够在客户端和服务器之间传输结构化数据(例如字典数据),并具备数据校验和纠错机制。请详细说明协议设计思路,包括数据格式、校验算法等,并给出Python实现的客户端和服务器端代码。
47.7万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试

协议设计思路

  1. 数据格式
    • 包头:固定长度,包含数据长度、校验和等元信息。
    • 数据体:实际传输的结构化数据,这里以字典数据为例,将字典序列化为JSON字符串传输。
    • 包头和数据体之间可以用特定分隔符分隔,例如|
  2. 校验算法:采用CRC(循环冗余校验)算法。CRC算法能有效检测出数据在传输过程中的错误。可以使用Python的crcmod库来实现CRC校验。

Python实现

服务器端代码

import socket
import json
import crcmod.predefined


def calculate_crc(data):
    crc16 = crcmod.predefined.Crc('crc-16')
    crc16.update(data.encode())
    return crc16.hexdigest()


server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('127.0.0.1', 12345))
server_socket.listen(1)

print('Server is listening on port 12345')

while True:
    client_socket, addr = server_socket.accept()
    print(f'Connected by {addr}')

    data = client_socket.recv(1024).decode()
    parts = data.split('|')
    received_crc = parts[0]
    json_data = parts[1]

    calculated_crc = calculate_crc(json_data)
    if received_crc == calculated_crc:
        try:
            dict_data = json.loads(json_data)
            print(f'Received data: {dict_data}')
            response = {'status':'success'}
            response_json = json.dumps(response)
            response_crc = calculate_crc(response_json)
            client_socket.send((response_crc + '|' + response_json).encode())
        except json.JSONDecodeError:
            response = {'status': 'error', 'message': 'Invalid JSON data'}
            response_json = json.dumps(response)
            response_crc = calculate_crc(response_json)
            client_socket.send((response_crc + '|' + response_json).encode())
    else:
        response = {'status': 'error', 'message': 'CRC check failed'}
        response_json = json.dumps(response)
        response_crc = calculate_crc(response_json)
        client_socket.send((response_crc + '|' + response_json).encode())

    client_socket.close()

客户端代码

import socket
import json
import crcmod.predefined


def calculate_crc(data):
    crc16 = crcmod.predefined.Crc('crc-16')
    crc16.update(data.encode())
    return crc16.hexdigest()


client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('127.0.0.1', 12345))

data_to_send = {'key': 'value'}
json_data = json.dumps(data_to_send)
crc = calculate_crc(json_data)
client_socket.send((crc + '|' + json_data).encode())

response = client_socket.recv(1024).decode()
response_parts = response.split('|')
received_crc = response_parts[0]
response_json = response_parts[1]

calculated_crc = calculate_crc(response_json)
if received_crc == calculated_crc:
    try:
        response_dict = json.loads(response_json)
        print(f'Server response: {response_dict}')
    except json.JSONDecodeError:
        print('Invalid JSON response from server')
else:
    print('CRC check failed for server response')

client_socket.close()