首页 > 代码库 > Python网络编程 (三)使用select.select()实现聊天服务器

Python网络编程 (三)使用select.select()实现聊天服务器

第一步, 实现通用的send()和receive()函数:

send函数定义通过cPicle.dumps()将需要发送的数据序列化,然后通过socket.htonl()方法将序列化后的数据长度转化为网络字节序格式,以便于底层传输,再将网络字节序格式的长度打包为‘L‘类型的C struct, 最后发送打包后的长度以及序列化后的数据

receive函数即是send反向过程,先接收到打包后的长度,将其解包,然后再主机序列化,所有数据接收完成以后,返回解除序列化后的原始数据。

 

 1 def send(channel, *args):
 2     data = http://www.mamicode.com/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 = http://www.mamicode.com/‘‘
16      while len(data) < data_size:
17           data = http://www.mamicode.com/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 =http://www.mamicode.com/ 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()实现聊天服务器