The first step is to implement the common send () and receive () functions:
The Send function definition serializes the data that needs to be sent via Cpicle.dumps () and then translates the serialized data length into network Byte-order format through the socket.htonl () method, for the underlying transport, and then packages the length of the network Byte-order format to the ' L ' type C struct, finally sending the packaged length and the serialized data
The receive function is the send reverse process, which first receives the packaged length, unpack it, and then serialize the host, and after all the data is received, it returns the original data after it is De-serialized.
1 defSend (channel, *args):2data = Cpickle.dumps (*Args)3Htonl_size =socket.htonl (len (data))4Size = Struct.pack ("L", Htonl_size)5 channel.send (size)6 channel.send (data)7 8 defReceive (channel):9Recv_size = Struct.calsize ("L")TenData_size = Channel.recv (recv_size)#Receive Size ' s value one Try: aSize = Socket.ntohl (struct.unpack ("L", Data_size) [0]) - exceptstruct.error, E: - return "' thedata ="' - whileLen (data) <data_size: -data = Channel.recv (data_size-Len (data)) - returnCpickle.loads (data)
The second step is to create the Chatserver class:
The chat room server needs to be able to do: 1, record the number of connections 2, record the client address of the connection and name mapping, return name Address 3 when needed, reuse address 4, detect keyboard interrupt 5, process input and request
First realize the 1,2,3,4 point:
1 classChatserver (object):2 def __init__(self, port, backlog=5):3Self.clients ="# Record Client number4Self.clientmap = {}#client address and name ' s mapping5Self.outputs = []#socket output objects ' list6Self.server =Socket.socket (socket.af_inet, Socket. Sock_stream)7Self.server.setsockopt (socket. sol_socket, SOCKET. so_reuseaddr, 1)8 self.server.bind (server_host, port)9 Self.server.listen (backlog)Ten signal.signal (signal. SIGINT, Self.sighandler) one a defsighandler (self, signum, frame): - Print "shutting down server ..." - forOutputinchoutputs: the output.close (0) - self.server.close () - - defget_client_name (self, client): +info =self.clientmap[client] -host, name = info[0][0], info[1] + return '@'. Join ((name, Host)) a
The 5th processing input and request in several cases, 1 processing client access and notify other clients, 2 processing client input information and forwarding to other clients, processing standard input, here discarded, 3 Processing exception
1 defRun (self):2Inputs = [self.server, sys.stdin]#inputs for Select.select () first arg3Self.outputs = []#define outputs for Select.select (), second arg4running =True5 whilerunning:6 Try:7readable, writeable, exceptional = 8 select.selcet (inputs, self.outputs, [])9 exceptselect.error, E:Ten break one a forSockinchreadable: - ifSock = =self.server: -client, address =self.server.accept () the Print "Chat server:got connection%d from%s"% \ - (client.fileno, Address) -CNAME = Receive (client). spilt ('NAME:') [1] -Self.clients + = 1 +Send (client,"CLIENT:"+Str (address[0]) - inputs.append (client) +self.clientmap[client] =(address, Cname) a #Send joining information to other clients atmsg ='\ n (connected:new client (%d) from%s "% - (self.clients, self.get_client_name (client))' - forOutputinchself.outputs: - Send (output, Msg) - self.outputs.append (client) - in elifSock = =sys.stdin: -Junk =sys.stdin.readable () torunning =False + Else: - Try: thedata =Receive (sock) * ifData: $msg ='\n#['+ Self.get_client_name (sock) + Panax Notoginseng ']>>'+Data - forOutputinchself.outputs: the ifoutput! =sock: + Send (output.msg) a Else: the Print "Chat server:%d Hung up"%Sock.fileno () +self.clients-= 1 - sock.close () $ Inputs.remove (sock) $ Self.outputs.remove (sock) -msg ='\ n (now hung up:client from%s)'% \ - sef.get_client_name (sock) the forOutputinchself.outputs: - Send (output, Msg)Wuyi exceptsocket.error, E: the Inputs.remove (sock) - Self.outputs.remove (sock) wu -Self.server.close ()
Python Network programming (iii) implementing a chat server using Select.select ()