[Python 網路編程] TCP Client (四)

來源:互聯網
上載者:User

標籤:sel   post   efi   reading   預設   pop   線程   簡單的   soc   

 

TCP Client

  • 用戶端編程步驟:
  • 建立socket對象
  • 串連到服務端的ip和port,connect()方法
  • 傳輸資料
    •   使用send、recv方法發送、接收資料
  • 關閉串連,釋放資源 

 

 

最簡單的用戶端:

#TCP Client用戶端import socketclient = socket.socket()client.connect((‘127.0.0.1‘,9999))client.send("Hi, I‘m client1.".encode())client.close()#運行

  

服務端狀態:

[16:08:25] [showthreads,1796] [<_MainThread(MainThread, started 9816)>, <Thread(show_client, started daemon 9344)>, <Thread(accept, started daemon 5908)>, <Thread(showthreads, started 1796)>][16:08:26] [accept,5908] <socket.socket fd=424, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=(‘127.0.0.1‘, 9999), raddr=(‘127.0.0.1‘, 5287)>-(‘127.0.0.1‘, 5287)[16:08:26] [show_client,9344] {(‘127.0.0.1‘, 5287): <_io.TextIOWrapper mode=‘rw‘ encoding=‘utf8‘>}2017/12/24 16:08:26 127.0.0.1:5287Hi, I‘m client1.[16:08:26] [recv,980] 2017/12/24 16:08:26 127.0.0.1:5287Hi, I‘m client1.[16:08:26] [recv,980] (‘127.0.0.1‘, 5287) quit[16:08:28] [showthreads,1796] [<_MainThread(MainThread, started 9816)>, <Thread(show_client, started daemon 9344)>, <Thread(accept, started daemon 5908)>, <Thread(showthreads, started 1796)>]

  

 

將上面的TCP Client封裝成類:

1)搭架子

#TCP Client用戶端 封裝成類import socketclass ChatClient:    def __init__(self):        pass    def start(self):        pass    def _recv(self):        pass    def send(self):        pass    def stop(self):        pass

  

2)基礎功能

用戶端:

#TCP Client用戶端 封裝成類import socket,threading,logging,datetimeDATEFMT="%H:%M:%S"FORMAT = "[%(asctime)s]\t [%(threadName)s,%(thread)d] %(message)s"logging.basicConfig(level=logging.INFO,format=FORMAT,datefmt=DATEFMT)class ChatClient:    def __init__(self,ip=‘127.0.0.1‘,port=9999):        self.sock = socket.socket()        self.addr = (ip,port)        self.event = threading.Event()        self.start()    def start(self):        self.sock.connect(self.addr)        # 準備接收資料,recv是阻塞的,啟動新的線程        threading.Thread(target=self._recv,name=‘recv‘).start()    def _recv(self):        while not self.event.is_set():            try:                data = self.sock.recv(1024) #阻塞            except Exception as e:                logging.info(e) #有任何異常保證退出                break            msg = "{:%H:%M:%S} {}:{}\n{}\n".format(datetime.datetime.now(),*self.addr,data.decode().strip())            # print(type(msg),msg)            logging.info("{}".format(data.decode()))    def send(self,msg:str):        data = "{}\n".format(msg.strip()).encode()        self.sock.send(data)    def stop(self):        logging.info("{} broken".format(self.addr))        self.sock.close()        self.event.wait(3)        self.event.set()        logging.info("byebye")def main():    e = threading.Event()    cc = ChatClient()    while True:        msg = input(">>> ")        if msg.strip() == ‘quit‘:            cc.stop()            break        cc.send(msg)if __name__ == ‘__main__‘:    main()

  

服務端:

#TCP Server 改裝成makefileimport threading,logging,time,random,datetime,socketDATEFMT="%H:%M:%S"FORMAT = "[%(asctime)s]\t [%(threadName)s,%(thread)d] %(message)s"logging.basicConfig(level=logging.INFO,format=FORMAT,datefmt=DATEFMT)class ChatServer:    def __init__(self,ip=‘127.0.0.1‘,port=9999): #啟動服務        self.addr = (ip,port)        self.sock = socket.socket()        self.event = threading.Event()        self.clients = {} #用戶端    def show_client(self):        while not self.event.is_set():            if len(self.clients) > 0:                logging.info(self.clients)                self.event.wait(3)    def start(self):        self.sock.bind(self.addr)        self.sock.listen()        # accept會阻塞主線程,所以開一個新線程        threading.Thread(target=self._accept,name=‘accept‘,daemon=True).start()        threading.Thread(target=self.show_client,name=‘show_client‘,daemon=True).start()    def stop(self):        for c in self.clients.values():            c.close()        self.sock.close()        self.event.wait(3)        self.event.set()    def _accept(self):        while not self.event.is_set(): #多人串連            conn,client = self.sock.accept()  #阻塞            f = conn.makefile(mode=‘rw‘)            self.clients[client] = f            logging.info("{}-{}".format(conn,client))            # recv 預設阻塞,每一個串連單獨起一個recv線程準備接收資料            threading.Thread(target=self._recv, args=(f, client), name=‘recv‘,daemon=True).start()    def _recv(self, f, client): #接收用戶端資料        while not self.event.is_set():            try:                data = f.readline()            except Exception:                data = ‘quit‘            finally:                msg = data.strip()                # Client通知退出機制                if msg == ‘quit‘:                    f.close()                    self.clients.pop(client)                    logging.info(‘{} quit‘.format(client))                    break            msg = "{:%Y/%m/%d %H:%M:%S} {}:{}\n{}\n".format(datetime.datetime.now(),*client,data)            # msg = data            print(msg)            logging.info(msg)            for c in self.clients.values():                # print(type(msg))                c.writelines(msg)                c.flush()cs = ChatServer()print(‘!!!!!!!!!!!‘)cs.start()print(‘~~~~~~~~~~~~~~~~~~~~‘)e = threading.Event()def showthreads(e:threading.Event):    while not e.wait(3):        logging.info(threading.enumerate())threading.Thread(target=showthreads,name=‘showthreads‘,args=(e,)).start()while not e.wait(1): # Sever控制台退出方式    cmd = input(‘>>> ‘).strip()    if cmd == ‘quit‘:        cs.stop()        e.wait(3)        break

  

運行結果:

#服務端~~~~~~~~~~~~~~~~~~~~>>> [17:26:14] [show_client,7824] {(‘127.0.0.1‘, 7517): <_io.TextIOWrapper mode=‘rw‘ encoding=‘cp936‘>}[17:26:14] [accept,3832] <socket.socket fd=400, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=(‘127.0.0.1‘, 9999), raddr=(‘127.0.0.1‘, 7517)>-(‘127.0.0.1‘, 7517)[17:26:15] [showthreads,5928] [<Thread(accept, started daemon 3832)>, <Thread(show_client, started daemon 7824)>, <Thread(recv, started daemon 2112)>, <_MainThread(MainThread, started 7412)>, <Thread(showthreads, started 5928)>][17:26:17] [show_client,7824] {(‘127.0.0.1‘, 7517): <_io.TextIOWrapper mode=‘rw‘ encoding=‘cp936‘>}[17:26:18] [showthreads,5928] [<Thread(accept, started daemon 3832)>, <Thread(show_client, started daemon 7824)>, <Thread(recv, started daemon 2112)>, <_MainThread(MainThread, started 7412)>, <Thread(showthreads, started 5928)>][17:26:19] [recv,2112] 2017/12/24 17:26:19 127.0.0.1:7517hello12017/12/24 17:26:19 127.0.0.1:7517hello1[17:26:20] [show_client,7824] {(‘127.0.0.1‘, 7517): <_io.TextIOWrapper mode=‘rw‘ encoding=‘cp936‘>}[17:26:21] [showthreads,5928] [<Thread(accept, started daemon 3832)>, <Thread(show_client, started daemon 7824)>, <Thread(recv, started daemon 2112)>, <_MainThread(MainThread, started 7412)>, <Thread(showthreads, started 5928)>][17:26:23] [show_client,7824] {(‘127.0.0.1‘, 7517): <_io.TextIOWrapper mode=‘rw‘ encoding=‘cp936‘>}[17:26:23] [accept,3832] <socket.socket fd=436, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=(‘127.0.0.1‘, 9999), raddr=(‘127.0.0.1‘, 7539)>-(‘127.0.0.1‘, 7539)[17:26:24] [showthreads,5928] [<Thread(show_client, started daemon 7824)>, <Thread(recv, started daemon 2112)>, <_MainThread(MainThread, started 7412)>, <Thread(accept, started daemon 3832)>, <Thread(recv, started daemon 6748)>, <Thread(showthreads, started 5928)>]2017/12/24 17:26:25 127.0.0.1:7539[17:26:25] [recv,6748] 2017/12/24 17:26:25 127.0.0.1:7539hello2hello2[17:26:26] [show_client,7824] {(‘127.0.0.1‘, 7517): <_io.TextIOWrapper mode=‘rw‘ encoding=‘cp936‘>, (‘127.0.0.1‘, 7539): <_io.TextIOWrapper mode=‘rw‘ encoding=‘cp936‘>}[17:26:27] [showthreads,5928] [<Thread(show_client, started daemon 7824)>, <Thread(recv, started daemon 2112)>, <_MainThread(MainThread, started 7412)>, <Thread(accept, started daemon 3832)>, <Thread(recv, started daemon 6748)>, <Thread(showthreads, started 5928)>][17:26:29] [show_client,7824] {(‘127.0.0.1‘, 7517): <_io.TextIOWrapper mode=‘rw‘ encoding=‘cp936‘>, (‘127.0.0.1‘, 7539): <_io.TextIOWrapper mode=‘rw‘ encoding=‘cp936‘>}[17:26:30] [showthreads,5928] [<Thread(show_client, started daemon 7824)>, <Thread(recv, started daemon 2112)>, <_MainThread(MainThread, started 7412)>, <Thread(accept, started daemon 3832)>, <Thread(recv, started daemon 6748)>, <Thread(showthreads, started 5928)>][17:26:32] [show_client,7824] {(‘127.0.0.1‘, 7517): <_io.TextIOWrapper mode=‘rw‘ encoding=‘cp936‘>, (‘127.0.0.1‘, 7539): <_io.TextIOWrapper mode=‘rw‘ encoding=‘cp936‘>}[17:26:33] [showthreads,5928] [<Thread(show_client, started daemon 7824)>, <Thread(recv, started daemon 2112)>, <_MainThread(MainThread, started 7412)>, <Thread(accept, started daemon 3832)>, <Thread(recv, started daemon 6748)>, <Thread(showthreads, started 5928)>][17:26:35] [show_client,7824] {(‘127.0.0.1‘, 7517): <_io.TextIOWrapper mode=‘rw‘ encoding=‘cp936‘>, (‘127.0.0.1‘, 7539): <_io.TextIOWrapper mode=‘rw‘ encoding=‘cp936‘>}[17:26:36] [showthreads,5928] [<Thread(show_client, started daemon 7824)>, <Thread(recv, started daemon 2112)>, <_MainThread(MainThread, started 7412)>, <Thread(accept, started daemon 3832)>, <Thread(recv, started daemon 6748)>, <Thread(showthreads, started 5928)>]

  

#用戶端1>>> hello1[17:26:19] [recv,2604] 2017/12/24 17:26:19 127.0.0.1:7517hello1>>> [17:26:25] [recv,2604] 2017/12/24 17:26:25 127.0.0.1:7539hello2[17:26:37] [recv,2604] [WinError 10054] 遠程主機強迫關閉了一個現有的串連。

  

#用戶端2>>> hello2>>> [17:26:25] [recv,4044] 2017/12/24 17:26:25 127.0.0.1:7539hello2[17:26:37] [recv,4044] [WinError 10054] 遠程主機強迫關閉了一個現有的串連。

  

 

以上例子在用戶端,如果服務端主動斷開,用戶端需要異常處理。

 

[Python 網路編程] TCP Client (四)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.