用Python製做只屬於你和ta的聊天渠道吧

前言

本文的文字及圖片來源於網絡,僅供學習、交流使用,不具備任何商業用途,版權歸原做者全部,若有問題請及時聯繫咱們以做處理。python

做者: Python應用寶典數據庫

PS:若有須要Python學習資料的小夥伴能夠加點擊下方連接自行獲取服務器

http://note.youdao.com/noteshare?id=3054cce4add8a909e784ad934f956cef微信

原理簡介網絡

在咱們今天的教程中,將用到即時通信的概念,即時通信容許兩人或多人同時使用網絡傳遞文字信息、文字、語音等。即時通信通常都基於socket鏈接,socket鏈接可用於發送或接受數據,通常的組合形式是IP+端口號。多線程

也就是說,在咱們的例子中,聊天的雙方,由一方要承擔「服務器 」 的責任,維持一個socket服務器,等待鏈接進入;另外一方則是「客戶端」,在服務器端維持等待狀態時便可發送請求,創建鏈接。socket

當你和ta想進入「小黑屋 」 裏聊天的時候,只有有一方充當服務器,另外一方充當客戶端便可,做爲「服務器端 」 的那我的,在微信中將IP和端口號告訴對方,便可構建鏈接,在小黑屋裏聊天,這個小黑屋裏的數據不會被任何數據庫保留(除非你本身作了一個保存的數據庫)。tcp

服務器端函數

聊天的時候,咱們有時候會遇到雙方同時發消息的狀況。這種聊天方式就叫全雙工聊天方式:「服務器」可向「客戶端」發送消息,「客戶端」也可向「服務端」發送消息,並且容許同時發送消息。學習

服務器端怎麼實現全雙工的聊天方式呢?其實很簡單,只要用多線程就好了,主線程用於接收客戶端的鏈接,鏈接成功後新建兩個線程:一個用於發送消息,一個用於接收消息:

首先,創建socket服務器:

 1 import socket
 2 import traceback
 3 # 設定ip和端口號
 4 host = ''
 5 port = 51423 
 6 # 創建socket服務器
 7 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
 8 s.bind((host,port))
 9 s.listen() 
10 while True:
11     # 等待鏈接
12     try:
13         clientsock, clientaddr = s.accept()
14     except KeyboardInterrupt:
15         raise
16     except:
17         traceback.print_exc()
18         continue 

 

其中,AF_INET指的是用IPv4進行通訊,而SOCK_STREAM指的是TCP協議。端口號你能夠隨意設定,服務器端的IP地址默認爲空便可。

在while循環中不斷等待用戶的鏈接。若是有用戶鏈接成功了,咱們將進入下一步,分別創建發送和接受線程:

1 # 創建接收線程
2 t = _thread.start_new_thread(processRecv, (clientsock,))
3  
4 # 創建發送線程
5 r = _thread.start_new_thread(processSend, (clientsock,)) 

 

clientsock就是咱們獲得的socket鏈接,processRecv和processSend分別用於處理接受信息和處理髮送信息:

 1 import _thread 
 2 def processRecv(clientsock):
 3     """
 4     接受消息
 5         :param clientsock: 客戶端的socket鏈接
 6     """
 7     while True:
 8         data = clientsock.recv(4096)
 9         if not len(data):
10             break
11         print (data.decode('utf-8'))
12     clientsock.close()
13  
14 def processSend(clientsock):
15     """
16     發送消息
17         :param clientsock: 客戶端的socket鏈接
18     """
19     while True:
20         data = input("> ")
21         data = data
22         clientsock.sendall(data.encode('utf-8'))
23     clientsock.close() 

 

有個小細節要注意,socket鏈接的sendall函數只支持bytes類型的數據,因此咱們要encode('utf-8')。

服務端的全部代碼就這樣,沒錯,就是這麼簡單。

客戶端

客戶端則更簡單,主線程自己設定爲接受消息,那麼咱們只須要多一個線程用於發送消息便可。客戶端的所有代碼以下:

 1 import _thread
 2 import sys
 3 from socket import *
 4  
 5 def send_message(tcpCliSock):
 6     """
 7     發送信息
 8         :param tcpCliSock: 與服務端的socket鏈接
 9     """
10     while True:
11         message = input('> ')
12         if not message:
13             break
14         tcpCliSock.send(message.encode('utf-8'))
15  
16     tcpCliSock.close()
17  
18 if(len(sys.argv) < 3):
19     HOST = 'localhost'
20     PORT = 51423
21 else:
22     HOST = sys.argv[1]
23     PORT = int(sys.argv[2])
24  
25 BUFSIZ = 1024
26 ADDR = (HOST,PORT)
27  
28 tcpCliSock = socket(AF_INET,SOCK_STREAM)
29 tcpCliSock.connect(ADDR)
30  
31 # 創建發送消息的線程
32 s = _thread.start_new_thread(send_message, (tcpCliSock,))
33  
34 while True:
35     rdata = tcpCliSock.recv(BUFSIZ)
36     if not rdata:
37         break
38     print (rdata.decode('utf-8'))
39     
40 tcpCliSock.close() 

 

其中,HOST部分填寫對方的IP,PORT部分填寫端口號。sys.argv用於經過參數輸入這兩個值,好比咱們將客戶端文件命名爲:client.py, 在cmd中輸入:

python client.py 127.0.0.1 51423

能直接傳入參數執行腳本,除此以外,其餘部分和服務端其實差很少。注意把接受到的數據decode一下(由於咱們發的時候encode了)。

相關文章
相關標籤/搜索