学习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。
那另一个呢?
很棒。服务器都能做出响应。
再发一条试试?
发现服务器没响应了,这是怎么回事呢"htmlcode">
data = s.recv(BUFSIZ)
因为recv方法是阻塞的,也就是说,当轮训到某个客户端,比如A,这句等待A发消息,不发消息就不往下走,所以此时B再去发消息的话服务器就收不到了。
那该怎么办呢?
很容易想到,将其设为非阻塞就好了。但上网找了好久,虽然找到可以用setblocking(0) 将套接字设为非阻塞,然而具体怎么用却很少有人讲清楚。查资料后终于搞明白,非阻塞的recv方法会继续向下执行,若超时得不到数据则会抛出异常。
修改后的代码如下:
#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: try: data = s.recv(BUFSIZ) #到这里程序继续向下执行 except Exception, e: continue 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 clientSock.setblocking(0) socks.append(clientSock)
此时再去尝试:
客户端随便输都会得到响应。任务达成!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新动态
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]