面试题答案
一键面试客户端消息接收和发送函数主要逻辑及关键方法
- 发送消息
- 主要逻辑:创建Socket对象后,连接到服务器指定的IP地址和端口。获取用户输入的消息,将其编码为字节流,然后通过Socket对象发送到服务器。
- 关键方法:
socket.socket()
:创建Socket对象,如s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
,AF_INET
表示使用IPv4地址,SOCK_STREAM
表示使用TCP协议。s.connect((server_ip, server_port))
:连接到服务器,server_ip
是服务器的IP地址,server_port
是服务器的端口号。s.sendall(message.encode())
:将消息编码后发送到服务器,sendall
方法会尝试发送所有数据,直到发送完毕或发生错误。
- 接收消息
- 主要逻辑:通过Socket对象接收服务器发送来的消息,将接收到的字节流解码为字符串并显示。
- 关键方法:
data = s.recv(buffer_size)
:接收服务器发送的消息,buffer_size
指定了一次接收的最大字节数,例如buffer_size = 1024
。message = data.decode()
:将接收到的字节流解码为字符串。
服务器端消息接收和发送函数主要逻辑及关键方法
- 发送消息
- 主要逻辑:创建Socket对象并绑定到指定的IP地址和端口,监听连接。接受客户端连接后,获取要发送给客户端的消息,编码为字节流并发送。
- 关键方法:
socket.socket()
:创建Socket对象,同客户端。s.bind((server_ip, server_port))
:绑定到指定的IP地址和端口。s.listen(backlog)
:开始监听连接,backlog
指定等待连接的最大数量,如backlog = 5
。conn, addr = s.accept()
:接受客户端连接,conn
是与客户端通信的新Socket对象,addr
是客户端的地址。conn.sendall(message.encode())
:向客户端发送消息。
- 接收消息
- 主要逻辑:通过与客户端通信的Socket对象接收客户端发送的消息,解码后进行处理。
- 关键方法:
data = conn.recv(buffer_size)
:从客户端接收消息,buffer_size
意义同客户端。message = data.decode()
:解码接收到的字节流。
避免消息接收和发送过程中的阻塞问题
- 使用非阻塞模式:
- 客户端:在创建Socket对象后,使用
s.setblocking(False)
将其设置为非阻塞模式。在发送和接收消息时,需要捕获BlockingIOError
异常。例如在接收消息时:
try: data = s.recv(buffer_size) if data: message = data.decode() print(message) except BlockingIOError: pass
- 服务器端:同样可以对监听Socket和与客户端通信的Socket设置非阻塞模式。对于监听Socket:
s.setblocking(False) try: conn, addr = s.accept() conn.setblocking(False) # 处理连接和消息 except BlockingIOError: pass
- 客户端:在创建Socket对象后,使用
- 使用多线程或异步编程:
- 多线程:在客户端和服务器端,可以为消息接收和发送分别创建线程。例如在客户端:
import threading def send_message(): while True: message = input("请输入消息: ") s.sendall(message.encode()) def receive_message(): while True: try: data = s.recv(buffer_size) if data: message = data.decode() print(message) except BlockingIOError: pass send_thread = threading.Thread(target = send_message) receive_thread = threading.Thread(target = receive_message) send_thread.start() receive_thread.start()
- 异步编程:在Python中可以使用
asyncio
库进行异步操作。例如在客户端:
import asyncio async def send_message(s): while True: message = input("请输入消息: ") await s.sendall(message.encode()) async def receive_message(s): while True: try: data = await s.recv(buffer_size) if data: message = data.decode() print(message) except BlockingIOError: pass async def main(): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((server_ip, server_port)) task1 = asyncio.create_task(send_message(s)) task2 = asyncio.create_task(receive_message(s)) await asyncio.gather(task1, task2) asyncio.run(main())