Python socket實現多對多全雙

服務器:#server.py

#!/usr/bin/env python  #-*-coding:utf-8-*-  import sys  import struct#將字符串打包為二進制流進行網絡傳輸  import select#  import signal#用於捕獲中斷信號  import cPickle#將python對象進行序列化:dumps將python對象序列化保存為字符串,loads與之相反  from socket import *  HOST = ''  def send(channel,*args):#發送數據      buffer = cPickle.dumps(args)      value = htonl(len(buffer))      size = struct.pack("L",value)      channel.send(size)      channel.send(buffer)  def receive(channel):#接收數據      size = struct.calcsize("L")      size = channel.recv(size)      try:          size = ntohl(struct.unpack("L",size)[0])#socket.ntohl(參考:http://blog.csdn.net/tatun/article/details/7194973)      except struct.error,e:          return ''      buf = ''      while len(buf) < size:          buf += channel.recv(size-len(buf))      return cPickle.loads(buf)[0]#恢復python對象    class ChatServer(object):      def __init__(self,PORT,backlog = 5):          self.clients = 0          self.clientmap = {}          self.outputs = [] #Client會話列表          self.server = socket(AF_INET, SOCK_STREAM)          self.server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)#重用套接字地址          self.server.bind((HOST,PORT))          self.server.listen(backlog)          signal.signal(signal.SIGINT,self.signalhandler)#使用signal模塊捕獲中斷操作 SIGINT中斷進程(ctrl+c), SIGTERM 終止進程,SIGKILL殺死進程,SIGALRM 鬧鐘信號        def signalhandler(self,signum,frame):#中斷處理方法          print "Shutting down server ..."          for output in self.outputs:              output.close()          self.server.close()        def get_client_name(self,client):          info = self.clientmap[client]          host,port,name = info[0][0],info[0][1],info[1]          return ':'.join((('@'.join((name,host))),str(port)))        def run(self):          inputs = [self.server]          print 'Waiting for connect...'          while True:              try:                  readable,writeable,execption = select.select(inputs,self.outputs,[])              except select.error,e:                  break              for sock in readable:                  if sock == self.server:#服務器端接收                      client,address = self.server.accept()                      print "Chat server: connected from",address                      self.clients += 1                      cname = receive(client)                      send(client,str(address[0]))                      inputs.append(client)                      self.clientmap[client] = (address,cname)                      msg = "(Connected : New Client(%d) from %s)n"%(self.clients,self.get_client_name(client))                      message = "At present, only one of you is in the chat room!"                      if self.clients == 1:                          send(client,message)                      for output in self.outputs:                          send(output,msg)                      self.outputs.append(client)#將開始回話的client加入Client回話列表                    #elif sock == sys.stdin:                      #break                  else:                      try:                          data = receive(sock)                          if data:                              msg = '[' + self.get_client_name(sock)+ '] >> ' + data                              for output in self.outputs:                                  if output!=sock:                                      send(output,msg)                          else:                              self.clients-=1                              sock.close()                              inputs.remove(sock)                              self.outputs.remove(sock)                              msg = '(Now hung up: Client from %s)'%self.get_client_name(sock)                              message = "At present, only one of you is in the chat room!"                              for output in self.outputs:                                  send(output,msg)                              if self.clients == 1:                                  send(self.outputs[0],message)                      except error,e:                          inputs.remove(sock)                          self.outputs.remove(sock)          self.server.close()  if __name__ == "__main__":          server = ChatServer(6004)          server.run()

客戶端:#client.py

#!/usr/bin/env python  #-*-coding:utf-8-*-  from server import send,receive  from socket import *  import sys  import select  import cPickle  import struct  import signal    class ChatClient(object):      def __init__(self,name):          self.name = name          self.connected = False          self.host = 'localhost'          self.port = 6004          try:              self.sock = socket(AF_INET,SOCK_STREAM)              self.sock.connect((self.host,self.port))              self.connected = True              send(self.sock,self.name)              data= receive(self.sock)              addr = data          except error,e:#socket.serro              print 'Failed to connect to chat server'              sys.exit(1)      def run(self):          while True:              try:                  readable,writeable,exception = select.select([0,self.sock],[],[])                  for sock in readable:                      if sock == 0:                          data = sys.stdin.readline().strip()                          if data:                              send(self.sock,data)                      else:                          data=receive(self.sock)                          if not data:                              print 'Client shutting down.'                              self.connected = False                              break                          else:                              sys.stdout.write(data+'n')                              sys.stdout.flush()              except KeyboardInterrupt:                  print 'Client interrupted'                  self.sock.close()                  break  if __name__ == "__main__":      name = raw_input("Please input login name > ")      client=ChatClient(name)      client.run()