tornado學習 - TCPClient 實現聊天功能


之前完成了一個簡單的聊天服務器,連接服務器使用的是系統自帶nc命令,接下來就是通過自己實現TCPClient.

客戶端與服務器功能大致相仿,相對與服務器只是少了轉發消息環節。

首先,定義TCPClient類,主要初始化hostportstream屬性。

class SimpleTCPClient:
    def __init__(self, host, port):
        self._host = host
        self._port = port
        self._stream = None
        self.EOF = b' end'

剛創建client實例時還未與服務器連接,所以_stream初始值為NoneEOF設置為消息的結尾,當讀到這個標識時表示一條消息輸出完畢。

    def get_stream(self):
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
        self._stream = tornado.iostream.IOStream(sock)
        self._stream.set_close_callback(self.on_close)

獲取socket,通過tornado.iostream.IOStream創建_stream
socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)中,其中第一個參數是namespace即使用的地址,這里的AF_INET表示使用IPv4地址,第二個參數是style,即socket的連接類型,這里使用的SOCK_STREAM是流式類型基於TCP。第三個參數是protocol指使用的協議類型,一般情況下使用0表示系統根據情況決定。

    def connect(self):
        self.get_stream()
        self._stream.connect((self._host, self._port), self.start)

定義連接服務器的方法,先獲取_stream然后連接服務器地址和指定端口,最后注冊回調函數就是開始客戶端運行的函數。

    def start(self):
        t1 = threading.Thread(target = self.read_msg)
        t2 = threading.Thread(target = self.send_msg)
        t1.daemon, t2.daemon = True, True
        t1.start()
        t2.start()

使用多線程同時通知收發消息。這里存在一個問題,使用多線程時,如果退出程序就必須要結束線程,否則會拋出異常,但是程序何時結束取決於用戶。為了解決這個問題,將線程設置為daemon線程,daemon線程可以在主程序結束時自動結束。

    def read_msg(self):
        self._stream.read_until(self.EOF, self.show_msg)
    
    def show_msg(self, data):
        print(to_unicode(data))
        self.read_msg()

接受並顯示消息。當數據中讀取到結束標識,調用打印消息的方法,消息打印完畢后再調用讀取方法,以此保持接收消息的狀態。

    def send_msg(self):
        while True:
            data = input()
            self._stream.write(bytes(data) + self.EOF) 

發送消息。使用while循環保持輸入狀態,當輸入完成講消息轉換為byte型,與消息結束標識拼接之后發送。

    def on_close(self):
        print('exit ...')
        quit()

用戶退出時關閉_stream會激活這個函數。

if __name__ == '__main__':
    try:
        client = SimpleTCPClient('localhost', 8888)
        client.connect()
        tornado.ioloop.IOLoop.instance().start()

到這里TCPClient基本完成。

之前絞盡腦汁不知道該如何解決同時保持收發信息的狀態,也有想過通過多線程的方式,但是轉念一想tornado時單線程的,擔心會有問題,然后就一直在糾結。
其實,編程不應該怕報錯或者崩潰,遇到問題解決問題這是提高自己的途徑,不應該對未知的感到擔心或害怕,多嘗試,大不了從頭寫過!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM