每日分享:
人们总是把幸福解读为“有”,有房、有车、有钱、有权。但幸福其实是“无”,无忧、无虑、无病、无灾。“有”多半是给别人看的,“无”才是你自己的。
一、需求之前开发的TCP服务器只能服务于一个客户端,如何开发一个多任务版的TCP服务端程序能够服务于多个客户端呢?
多任务可以使用线程,比进程更节省内存资源
二、具体实现步骤- 编写一个TCP服务端程序,循环等待接收客户端的连接请求
- 当客户端和服务端建立连接成功,创建子线程,使用子线程专门处理客户端的请求,防止主线程阻塞
- 把创建的子线程设置为守护主线程,防止主线程无法退出
import socket
import threading
def more_socket(new_client1, ip_port1):
print("客户端的ip和端口号:", ip_port1)
# 循环接收客户端发送的数据
while True:
# 5.接收客户端的数据
recv_data = new_client1.recv(1024)
# 如果客户端直接断开,则recv_data会接收recv的返回值0
if recv_data:
# 对二进制数据进行解码变成字符串
recv_content = recv_data.decode('gbk')
print("接收客户端的数据:", recv_content, ip_port1)
# 6.发送数据到客户端
send_content = '问题处理中...'
# 二进制编码
send_data = send_content.encode('gbk')
new_client1.send(send_data)
else:
print("客户端已下线!", ip_port1)
break
# 结束本次服务
new_client1.close()
if __name__ == '__main__':
# 1.创建tcp服务端套接字
# AF_INET:ipv4 AF_INET6:ipv6 SOCK_STREAM:tcp协议
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置端口号复用,程序退出,端口号立即释放
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 2.绑定端口号
# 第一个参数表示ip地址,一般不用指定,表示本机的任何一个ip都可
# 第二个参数表示端口号
tcp_server_socket.bind(("", 8080))
# 3.设置监听
# 128(可自定义)表示最大等待建立连接的个数
tcp_server_socket.listen(128)
# 4.等待接收客户端的连接请求
# 每次客户端和服务端建立连接成功都会返回一个新的套接字
# tcp_server_socket只负责等待接收客户端的连接请求,收发消息不使用它
# 一般来说服务端要一直运行,来服务客户端,所以不用跳出循环
while True:
new_client, ip_port = tcp_server_socket.accept()
# 代码执行至此表示连接成功
# 客户端与服务端连接成功后,就要创建一个子线程来完成信息的收发
sub_thread = threading.Thread(target=more_socket, args=(new_client, ip_port))
# 守护主线程(无论子线程有没有执行完,关闭主线程,程序直接结束)
sub_thread.setDaemon(True)
# 启动子线程
sub_thread.start()
# 7.关闭服务端套接字,表示服务端以后不在接收等待接收客户端的连接请求
# tcp_server_socket.close()
结果:
1. 编写一个TCP服务端程序,循环等待接收客户端的连接请求
while True: new_client, ip_port = tcp_server_socket.accept()
2. 当客户端和服务端建立连接成功,创建子线程,使用子线程专门处理客户端请求,防止主线程阻塞
while True: new_client, ip_port = tcp_server_socket.accept() sub_thread = threading.Thread(target=more_socket, args=(new_client, ip_port)) sub_thread.start()
3. 把创建的子线程设置成守护主线程,防止主线程无法退出
sub_thread.setDaemon(True)