基於select的python聊天室程式,selectpython聊天室

來源:互聯網
上載者:User

基於select的python聊天室程式,selectpython聊天室

python網路編程具體參考《python select網路編程詳細介紹》。

在python中,select函數是一個對底層作業系統的直接存取的介面。它用來監控sockets、files和pipes,等待IO完成(Waiting for I/O completion)。當有可讀、可寫或是例外狀況事件產生時,select可以很容易的監控到。select.select(rlist, wlist, xlist[, timeout]) 傳遞三個參數,一個為輸入而觀察的檔案對象列表,一個為輸出而觀察的檔案對象列表和一個觀察錯誤異常的檔案清單。第四個是一個選擇性參數,表示逾時秒數。其返回3個tuple,每個tuple都是一個準備好的對象列表,它和前邊的參數是一樣的順序。

聊天室程式如下。運行多個client,則可互相聊天,輸入"exit"即可退出

伺服器代碼

#!/bin/env python#-*- coding:utf8 -*-"""server select"""import sysimport timeimport socketimport selectimport loggingimport Queueg_select_timeout = 10class Server(object):    def __init__(self, host='10.1.32.80', port=33333, timeout=2, client_nums=10):        self.__host = host        self.__port = port        self.__timeout = timeout        self.__client_nums = client_nums        self.__buffer_size = 1024        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)        self.server.setblocking(False)        self.server.settimeout(self.__timeout)        self.server.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) #keepalive        self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) #連接埠複用        server_host = (self.__host, self.__port)        try:            self.server.bind(server_host)            self.server.listen(self.__client_nums)        except:            raise        self.inputs = [self.server] #select 接收檔案描述符列表          self.outputs = [] #輸出檔案描述符列表        self.message_queues = {}#訊息佇列        self.client_info = {}    def run(self):        while True:            readable , writable , exceptional = select.select(self.inputs, self.outputs, self.inputs, g_select_timeout)            if not (readable or writable or exceptional) :                continue            for s in readable :                if s is self.server:#是用戶端串連                    connection, client_address = s.accept()                    #print "connection", connection                    print "%s connect." % str(client_address)                    connection.setblocking(0) #非阻塞                    self.inputs.append(connection) #用戶端添加到inputs                    self.client_info[connection] = str(client_address)                    self.message_queues[connection] = Queue.Queue()  #每個用戶端一個訊息佇列                else:#是client, 資料發送過來                    try:                        data = s.recv(self.__buffer_size)                    except:                        err_msg = "Client Error!"                        logging.error(err_msg)                    if data :                        #print data                        data = "%s %s say: %s" % (time.strftime("%Y-%m-%d %H:%M:%S"), self.client_info[s], data)                        self.message_queues[s].put(data) #隊列添加訊息                                                 if s not in self.outputs: #要回複訊息                            self.outputs.append(s)                    else: #用戶端斷開                        #Interpret empty result as closed connection                        print "Client:%s Close." % str(self.client_info[s])                        if s in self.outputs :                            self.outputs.remove(s)                        self.inputs.remove(s)                        s.close()                        del self.message_queues[s]                        del self.client_info[s]            for s in writable: #outputs 有訊息就要發出去了                try:                    next_msg = self.message_queues[s].get_nowait()  #非阻塞擷取                except Queue.Empty:                    err_msg = "Output Queue is Empty!"                    #g_logFd.writeFormatMsg(g_logFd.LEVEL_INFO, err_msg)                    self.outputs.remove(s)                except Exception, e:  #發送的時候用戶端關閉了則會出現writable和readable同時有資料,會出現message_queues的keyerror                    err_msg = "Send Data Error! ErrMsg:%s" % str(e)                    logging.error(err_msg)                    if s in self.outputs:                        self.outputs.remove(s)                else:                    for cli in self.client_info: #發送給其他用戶端                        if cli is not s:                            try:                                cli.sendall(next_msg)                            except Exception, e: #發送失敗就關掉                                err_msg = "Send Data to %s  Error! ErrMsg:%s" % (str(self.client_info[cli]), str(e))                                logging.error(err_msg)                                print "Client: %s Close Error." % str(self.client_info[cli])                                if cli in self.inputs:                                    self.inputs.remove(cli)                                    cli.close()                                if cli in self.outputs:                                    self.outputs.remove(s)                                if cli in self.message_queues:                                    del self.message_queues[s]                                del self.client_info[cli]            for s in exceptional:                logging.error("Client:%s Close Error." % str(self.client_info[cli]))                if s in self.inputs:                    self.inputs.remove(s)                    s.close()                if s in self.outputs:                    self.outputs.remove(s)                if s in self.message_queues:                    del self.message_queues[s]                del self.client_info[s]        if "__main__" == __name__:    Server().run()

用戶端代碼

#!/usr/local/bin/python# *-* coding:utf-8 -*-"""client.py"""import sysimport timeimport socketimport threadingclass Client(object):    def __init__(self, host, port=33333, timeout=1, reconnect=2):        self.__host = host        self.__port = port        self.__timeout = timeout        self.__buffer_size = 1024        self.__flag = 1        self.client = None        self.__lock = threading.Lock()         @property    def flag(self):        return self.__flag    @flag.setter    def flag(self, new_num):        self.__flag = new_num    def __connect(self):        client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)        #client.bind(('0.0.0.0', 12345,))        client.setblocking(True)        client.settimeout(self.__timeout)        client.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) #連接埠複用        server_host = (self.__host, self.__port)        try:            client.connect(server_host)        except:            raise        return client    def send_msg(self):        if not self.client:            return        while True:            time.sleep(0.1)            #data = raw_input()            data = sys.stdin.readline().strip()            if "exit" == data.lower():                with self.__lock:                    self.flag = 0                break            self.client.sendall(data)        return    def recv_msg(self):        if not self.client:            return        while True:            data = None            with self.__lock:                if not self.flag:                    print 'ByeBye~~'                    break            try:                data = self.client.recv(self.__buffer_size)            except socket.timeout:                continue            except:                raise            if data:                print "%s\n" % data            time.sleep(0.1)        return    def run(self):        self.client = self.__connect()        send_proc = threading.Thread(target=self.send_msg)        recv_proc = threading.Thread(target=self.recv_msg)        recv_proc.start()        send_proc.start()        recv_proc.join()        send_proc.join()        self.client.close()if "__main__" == __name__:    Client('10.1.32.80').run()

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.