标签:nts rgs try 信息 socket nal 通过 pack cts
第一步, 实现通用的send()和receive()函数:
send函数定义通过cPicle.dumps()将需要发送的数据序列化,然后通过socket.htonl()方法将序列化后的数据长度转化为网络字节序格式,以便于底层传输,再将网络字节序格式的长度打包为‘L‘类型的C struct, 最后发送打包后的长度以及序列化后的数据
receive函数即是send反向过程,先接收到打包后的长度,将其解包,然后再主机序列化,所有数据接收完成以后,返回解除序列化后的原始数据。
1 def send(channel, *args): 2 data = cPickle.dumps(*args) 3 htonl_size = socket.htonl(len(data)) 4 size = struct.pack("L", htonl_size) 5 channel.send(size) 6 channel.send(data) 7 8 def receive(channel): 9 recv_size = struct.calsize("L") 10 data_size = channel.recv(recv_size) # receive size‘s value 11 try: 12 size = socket.ntohl(struct.unpack("L", data_size)[0]) 13 except struct.error, e: 14 return ‘‘ 15 data = ‘‘ 16 while len(data) < data_size: 17 data = channel.recv(data_size - len(data)) 18 return cPickle.loads(data)
第二步,创建ChatServer类:
聊天室服务器需要能做到: 1,记录连接数 2,记录连接的客户端地址以及名称映射 ,需要时返回名称地址 3,重用地址 4,检测键盘中断 5,处理输入及请求
先实现1,2,3,4点:
1 class ChatServer(object): 2 def __init__(self, port, backlog=5): 3 self.clients = " # record client number 4 self.clientmap = {} # client address and name‘s mapping 5 self.outputs = [] # socket output objects‘ list 6 self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 7 self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 8 self.server.bind((SERVER_HOST, port) 9 self.server.listen(backlog) 10 signal.signal(signal.SIGINT, self.sighandler) 11 12 def sighandler(self, signum, frame): 13 print "Shutting down server..." 14 for output in outputs: 15 output.close(0) 16 self.server.close() 17 18 def get_client_name(self, client): 19 info = self.clientmap[client] 20 host, name = info[0][0], info[1] 21 return ‘@‘.join((name, host)) 22
第5点处理输入及请求分几种情况,1处理客户端接入并通知其他客户端,2处理客户端输入信息并转发给其他客户端,处理标准输入, 这里丢弃,3处理异常
1 def run(self): 2 inputs = [self.server, sys.stdin] #inputs for select.select() first arg 3 self.outputs = [] # define outputs for select.select(), second arg 4 running = True 5 while running: 6 try: 7 readable, writeable, exceptional = 8 select.selcet(inputs, self.outputs, []) 9 except select.error, e: 10 break 11 12 for sock in readable: 13 if sock == self.server: 14 client, address = self.server.accept() 15 print "Chat server: got connection %d from %s" % \ 16 (client.fileno, address) 17 cname = receive(client).spilt(‘NAME: ‘)[1] 18 self.clients += 1 19 send(client, "CLIENT: " + str(address[0]) 20 inputs.append(client) 21 self.clientmap[client] = (address, cname) 22 # send joining information to other clients 23 msg = ‘\n (Connected: New client (%d) from %s" % 24 (self.clients, self.get_client_name(client))‘ 25 for output in self.outputs: 26 send(output, msg) 27 self.outputs.append(client) 28 29 elif sock == sys.stdin: 30 junk = sys.stdin.readable() 31 running = False 32 else: 33 try: 34 data = receive(sock) 35 if data: 36 msg = ‘\n#[‘ + self.get_client_name(sock) + 37 ‘]>>‘ + data 38 for output in self.outputs: 39 if output != sock: 40 send(output.msg) 41 else: 42 print "Chat server: %d hung up" % sock.fileno() 43 self.clients -= 1 44 sock.close() 45 inputs.remove(sock) 46 self.outputs.remove(sock) 47 msg = ‘\n(now hung up: client from %s)‘ % \ 48 sef.get_client_name(sock) 49 for output in self.outputs: 50 send(output, msg) 51 except socket.error, e: 52 inputs.remove(sock) 53 self.outputs.remove(sock) 54 55 self.server.close()
Python网络编程 (三)使用select.select()实现聊天服务器
标签:nts rgs try 信息 socket nal 通过 pack cts
原文地址:http://www.cnblogs.com/yangxintang/p/6034915.html