MST

星途 面试题库

面试题:Python 实现高效网络通信之基础套接字使用

请用 Python 的 socket 模块实现一个简单的 TCP 服务器和客户端,要求服务器能接收客户端发送的消息并回显。请阐述在实现过程中如何处理连接建立、数据传输和关闭连接等操作,以及可能会遇到的常见错误及解决办法。
10.5万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试

TCP 服务器实现

import socket


def tcp_server():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server_address = ('localhost', 8888)
    server_socket.bind(server_address)
    server_socket.listen(1)
    print('Server is listening on {}:{}'.format(*server_address))

    try:
        while True:
            client_socket, client_address = server_socket.accept()
            print('Accepted connection from {}:{}'.format(*client_address))
            try:
                while True:
                    data = client_socket.recv(1024)
                    if data:
                        print('Received: {}'.format(data.decode('utf - 8')))
                        client_socket.sendall(data)
                    else:
                        break
            finally:
                client_socket.close()
                print('Connection with {}:{} closed'.format(*client_address))
    finally:
        server_socket.close()


if __name__ == '__main__':
    tcp_server()


TCP 客户端实现

import socket


def tcp_client():
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_address = ('localhost', 8888)
    client_socket.connect(server_address)
    try:
        message = 'Hello, Server!'
        client_socket.sendall(message.encode('utf - 8'))
        data = client_socket.recv(1024)
        print('Received: {}'.format(data.decode('utf - 8')))
    finally:
        client_socket.close()


if __name__ == '__main__':
    tcp_client()


操作处理

  1. 连接建立
    • 服务器:使用 socket.socket() 创建套接字对象,指定地址族 AF_INET(IPv4)和套接字类型 SOCK_STREAM(TCP)。通过 setsockopt 设置 SO_REUSEADDR 选项,允许地址重用,避免 Address already in use 错误。调用 bind 方法绑定服务器地址和端口,然后使用 listen 方法开始监听连接,参数指定最大连接数。
    • 客户端:同样创建套接字对象,使用 connect 方法连接到服务器的地址和端口。
  2. 数据传输
    • 服务器:在接受客户端连接后,进入一个循环,使用 recv 方法接收客户端发送的数据,recv 方法的参数指定接收缓冲区的大小。接收到数据后进行处理(这里是回显),使用 sendall 方法将数据发送回客户端。
    • 客户端:使用 sendall 方法向服务器发送数据,然后使用 recv 方法接收服务器回显的数据。
  3. 关闭连接
    • 服务器:当客户端关闭连接或没有数据可读时,服务器关闭与该客户端的连接,通过调用 client_socket.close()。当服务器程序结束时,关闭服务器套接字 server_socket.close()
    • 客户端:在完成数据传输后,调用 client_socket.close() 关闭连接。

常见错误及解决办法

  1. Address already in use
    • 原因:服务器程序上次运行后,端口没有及时释放。
    • 解决办法:在服务器创建套接字后,设置 SO_REUSEADDR 选项,如上述代码中的 server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  2. Connection refused
    • 原因:客户端尝试连接时,服务器可能未启动,或者服务器监听的地址和端口与客户端连接的不一致。
    • 解决办法:确保服务器已正确启动并监听指定的地址和端口,检查客户端连接的地址和端口是否与服务器一致。
  3. Timeout
    • 原因:在规定时间内未完成连接建立或数据传输。
    • 解决办法:可以适当调整连接超时和接收超时时间,通过 setsockopt 设置 SO_RCVTIMEOSO_SNDTIMEO 选项来设置接收和发送超时时间。例如:client_socket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, 10)(设置接收超时为 10 秒)。