Python通過Socket實作QQ聊天功能@TOC
來源:https://blog.csdn.net/huokundian/article/details/90668862
伺服器端代碼tcp_server_chat.py
#/usr/bin/python3
import socket
import threading
import chat
if __name__ == '__main__':
# 初始化socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 綁定IP位址和端口
server.bind(("localhost", 8888))
# 設定最大監聽數
server.listen(5)
# 設定一個字典,用來儲存每一個用戶端的連接配接 和 身份資訊
socket_mapping = {}
# 開啟準備等待擷取用戶端的連結
while True:
sc, addr = server.accept()
# 為每一個用戶端開啟一個線程、保證程式的高效運作
threading.Thread(target=chat.server_chat, args=(sc, socket_mapping)).start()
用戶端代碼tcp_client_chat.py
#/usr/bin/python3
import socket
import threading
import chat
class QQClient:
"""
QQ Client
"""
def __init__(self, qq):
"""
初始化QQ号、并建立連結
:param qq:
"""
self.qq = qq
# 建立 socket 用戶端
self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 連接配接伺服器
self.client.connect(("localhost", 8888))
# 發送自己的身份,給伺服器
self.client.send(self.qq.encode())
def chat(self, to_qq):
"""
和誰聊天
:param to_qq:
:return:
"""
# 開啟兩個線程、分别進行接收(讀取)資料、和發送(寫入)資料
threading.Thread(target=chat.read_chat, args=(self.client,)).start()
threading.Thread(target=chat.write_chat, args=(self.client, to_qq)).start()
chat.py
#/usr/bin/python3
def read_chat(socket): # 誰發送的、發送的内容
"""
讀取别人發送過來的資料
:param socket:
:return:
"""
while True:
try:
msg = socket.recv(1024).decode()
# 将接收到的資訊、列印到控制台上
print(msg)
except ConnectionResetError:
print("伺服器連接配接失敗、請重新連接配接~")
break
def write_chat(socket, to_qq): # 誰發的、發給誰的、内容
"""
發送資訊給to_qq
:param socket:
:param to_qq:
:return:
"""
while True:
msg = input()
# 準備發送給伺服器的内容
msg = f"{to_qq}:{msg}"
# 将資訊發送給伺服器
try:
socket.send(msg.encode())
except ConnectionResetError:
print("伺服器連接配接失敗、請重新連接配接~")
break
def server_chat(socket, socket_mapping):
"""
伺服器處理資料、并實作兩個用戶端的互動
:param socket:
:param socket_mapping:
:return:
"""
# 接收用戶端的身份、并進行存儲
qq = socket.recv(1024).decode()
# 存儲身份(這裡也可以實作不允許同一賬戶多次登入)
socket_mapping[qq] = socket
# 給所有socket 顯示 該使用者上線了
for k, v in socket_mapping.items():
v.send(f"【{qq}】上線了".encode())
# 開啟循環、用來不斷的進行轉發資料
while True:
try:
# 接收用戶端發送的資訊
data = socket.recv(1024).decode()
to_qq, msg = data.split(":", 1)
# 将資訊轉發給 to_qq 對應的用戶端
to_socket = socket_mapping[to_qq]
# 将資訊發送給 to_socket
to_socket.send(f"{qq}:{msg}".encode())
except ConnectionResetError:
# 該用戶端離線了
socket_mapping.pop(qq)
# 提示所有的用戶端、該使用者下線了
for k, v in socket_mapping.items():
v.send(f"【{qq}】下線了".encode())
# 退出循環
break
except KeyError:
# 該使用者不線上、提示fqq,您的好友不線上
socket.send(f"您的好友【{to_qq}】不線上".encode())
測試代碼
// client1
#/usr/bin/python3
from tcp_client_chat import QQClient
if __name__ == '__main__':
# 登入QQ、并和伺服器建立連接配接、模拟登入
qq = QQClient("13523456")
# 開啟聊天
qq.chat("472759903")
// client2
from tcp_client_chat import QQClient
if __name__ == '__main__':
# 登入QQ、并和伺服器建立連接配接、模拟登入
qq = QQClient("472759903")
# 開啟聊天
qq.chat("13523456")