学习Python网络通信的时候发现书上只有一个服务端对应一个客户端的情形,于是自己想自己动手实现一个服务端响应多个客户端。
首先建立服务器的socket来监听客户端的请求:
tcpSerSock=socket(AF_INET,SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)
这样服务器的监听socket就建好了。
接下来的思路是,如果要监听多个客户端,则
tcpSerSock.accept() #(accept()是阻塞式的)
必须放进一个while循环(不放进循环监听一次就没了)。然而,这里就有问题了。如果按照一对一的那种处理顺序,客户端A连进来后,程序顺序向下执行,服务端要再写一个while循环,用来处理客户端A的请求,如果此时客户端B再来请求,服务器将接收不到。于是,很自然想到,将监听和处理放到不同的线程进行处理。我选择将监听放入主线程,将处理放进子线程。该服务器功能为接收到客户端的数据加上时间戳后返回给客户端。服务端完整代码如下:
#coding=utf-8
#!/usr/bin/env python
'''''
author:Mr.Jing
created on Fri Sep 22 14:29:03 2017
platfrom:win10,python2.7
'''
from socket import *
from time import ctime
import threading
import time
HOST=''
PORT=2159
BUFSIZ=1024
ADDR = (HOST,PORT)
tcpSerSock=socket(AF_INET,SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)
socks=[] #放每个客户端的socket
def handle():
while True:
for s in socks:
data = s.recv(BUFSIZ)
if not data:
socks.remove(s)
continue
s.send('[%s],%s' % (ctime(), data)) #加上时间戳返回
t = threading.Thread(target=handle) #子线程
if __name__ == '__main__':
t.start()
print u'我在%s线程中 ' % threading.current_thread().name #本身是主线程
print 'waiting for connecting...'
while True:
clientSock,addr = tcpSerSock.accept()
print 'connected from:', addr
socks.append(clientSock)
两个客户端A和B同时连接,服务器输出:
可以看到服务端是可以相应多个客户端的。
客户端A发条消息试试?
服务器返回来了带时间戳的消息,goodjob。
那另一个呢?
很棒。服务器都能做出响应。
再发一条试试?
发现服务器没响应了,这是怎么回事呢?
经过仔细勘察发现是因为这句: