目前代码存在的问题
前面我们已经完成了基于 SOCKET 的实现了通信循环的简单套接字通信程序,并且还优化了其中的两个小问题,让程序更加稳定。
但俗话说的好,“旧的刚忘掉,新的就来到”,所以我们很无奈的发现了一个问题,就是我们的程序只能实现一个客户端同服务端 “对话” ,而很显然这和我们现实的要求肯定相去甚远——在现实中我们不可能有一个只服务一个客户的服务端(即要服务不同的客户就必须重启程序)。
所以这时候我们就需要使用所谓的 链接循环。
解决方案——原代码分析
因为我们的目的是让服务端可以同时服务多个客户端,所以我们的链接循环应该在服务端的代码上进行修改。而要添加 链接循环,首先就要明白什么是链接,或者说链接在客户端的代码里是怎么体现的。
这是我们之前服务端的代码
import socket
# 买手机
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 表示端口可以重复使用
# 装上手机卡
phone.bind(("127.0.0.1", 8080))
# 开机
phone.listen(5)
# 等待电话
conn, client_addr = phone.accept()
# 收发信息
while True: # 通信循环
try:
data = conn.recv(1024)
print(data)
if not data: # 若客户端发送的信息为空
break
print("客户端发送的消息:", data)
conn.send(data.upper())
except ConnectionResetError:
break
# 挂电话
conn.close()
# 关机
phone.close()
我们还是用 打电话 的例子来说明。链接嘛,顾名思义就是服务端和客户端产生联系,所以在打电话的类比中,打电话的双方产生联系的过程就是等待电话到挂电话的过程,而这个过程也就是我们需要添加循环的过程。
注意以下代码的含义
phone.listen(5)
这里的 5 是指该服务端可以一次性接通 5 个客户端,即第 6 个客户端无法连接。
代码实现
只需要修改服务端代码
# coding=gbk
import socket
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
phone.bind(("127.0.0.1", 8080))
phone.listen(5)
while True: # 连接循环
conn, addr = phone.accept()
print("staring……")
print(addr)
while True:
try:
data = conn.recv(1024)
if not data:
break
print("客户端的信息是", data.decode("utf-8"))
conn.send(data.upper())
except ConnectionResetError:
break
conn.close()
phone.close()
运行结果
值得注意的是,因为服务端的代码并没有实现多线程,所以服务端虽然同时连接了两个客户端,所以只有把其中一个客户端停止连接,另一个客户端的信息才能传到服务端。
运行结果如下
服务端
客户端
客户端1