使用python基于socket的tcp服务器聊天室
生活随笔
收集整理的這篇文章主要介紹了
使用python基于socket的tcp服务器聊天室
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
# coding=utf-8
import socket,threading,time
'''代碼說明:1.創建一個字典用于接受客戶端的用戶名和信息2.創建一個類對象client用于編寫客戶端套接字對象發送(sendMsg)、接收數據(recv)獲取用戶名(getID)、關閉服務器(close)和獲取時間(getTime)方法3.創建函數new_client用于接收客戶端的用戶名和數據進行打印創建broadcast方法進行服務器數據的發送4.創建start_server用于開啟服務器,將new_client定義為線程進行數據收發'''
# 創建客戶端存儲對象
clients={}
class client(object):def __init__(self,socket,addr,username):# 創建連接地址對象self.addr=addr[0]self.port=addr[1]# 創建用戶名對象self.username=username# 創建套接字對象self.socket=socket'''用于發送數據'''def sendMsg(self,msg,username,admin):try:if admin:# 以管理員身份發送數據self.socket.send("%s %s(管理員):%s"%(self.getTime(),username,msg).encode("utf-8"))else:self.socket.send("%s %s:%s"%(self.getTime(),username,msg).encode("utf-8"))return Trueexcept:return False'''用于接收套接字對象的數據'''def recv(self,mtu=1024):try:# 接收套接字對象的數據data=self.socket.recv(mtu)if data=='!q' or data is None:return Falsereturn dataexcept:return False'''用于關閉套接字對象'''def close(self):try:# 關閉套接字對象self.socket.close()return Trueexcept:return False'''用于獲取用戶名'''def getID(self):return "%s-%s" %(self.addr,self.port)'''用于獲取當前時間'''def getTime(self):# 以年月日時分秒的形式返回當前時間return str(time.strftime("%Y-%m-%d %H:%M:%S"))
'''用于創建套接字對象并獲取用戶名和數據'''
def new_client(c):try:# 開始連接print("%s(%s)嘗試連接" %(c.addr,c.port))data=c.recv()# 設置用戶名不為空if data is None:print("用戶名不能為空")return False# 規定用戶名長度if len(data)>16:print("用戶名太長")return False# 將數據傳回usernamec.username=dataprint("用戶%s %s(%s)已連接" %(c.username,c.addr,c.port))# 將連接成功的數據傳回服務端c.socket.send("已連接:".encode("utf-8"))while True:# 接收客戶端發送的數據data=c.recv()if data is None:breakelse:print("用戶%s %s(%s)發送了:%s" %(c.username,c.addr,c.port,data))broadcast(data,c.username)# 打印關于socket的錯誤except socket.error as e:print("套接字錯誤:%s" % str(e))# 打印其他錯誤except Exception as e:print("其他錯誤:%s" %str(e))# 關閉服務端finally:print("%s(%s) 斷開連接" %(c.addr,c.port))c.close()# 根據用戶名刪除客戶端的信息global clientclients.pop(c.getID())
# 用于發送客戶端的所有信息
def broadcast(msg,username,admin=False):for c in clients.values():c.sendMsg(msg,username,admin)
'''用于創建并開啟套接字對象'''
def start_server(port):server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)# 設置服務端套接字對象可復用IP地址server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)# 設置本機IPhost="192.168.189.1"# 給服務端綁定固定的IP地址和端口server.bind((host,port))# 監聽客戶端,最多十個客戶同時連入server.listen(10)print(f"服務器開啟,正在監聽{server.getsockname()}")while True:# 接收客戶端收到的信息conn,addr=server.accept()c=client(conn,addr,"")# 將輸入的用戶名傳給客戶端套接字clients[c.getID()]=ct=threading.Thread(target=new_client,args=(c,)).start()
'''主函數'''
if __name__ == '__main__':start_server(7879)
TCP服務端
# coding=utf-8 import socket import time from socket import * from threading import Thread from time import sleep import sys '''代碼說明:再main函數中創建一個空IP地址,開始掃描服務器,當連接到服務器時自動分配同網段的IP,若同意連接則將IP傳入空IP若不連接則退出程序,創建兩個線程分別用于接收服務端數據和發送數據給服務端,開啟一個線程用于接收數據,當接收到數據時開啟發送數據線程,當輸入!q或者不輸入數據時結束程序,實現客戶端的收發 ''' # 設置開啟客戶端的標志位 running=False '''設置發送數據的方法''' def send(client):# 每次發送數據都延遲0.5stime.sleep(0.5)while True:data=input("")client.send(data.encode("utf-8"))if data=='!q' or not data:running=Falsebreak '''設置接收數據的方法''' def recv(client,t2):# 每次連接成功后先輸入用戶名username=input("輸入用戶名")# 發送用戶名到服務端client.send(username.encode("utf-8"))# 開啟發送數據的進程t2.start()while running:try:data=client.recv(1024).decode("utf-8")if not data:breakprint(data)except:break'''主函數''' if __name__ == '__main__':# 創建主機IPip=""# 獲取客戶端套接字的IP地址(gethostname是獲取主機名)addrs=getaddrinfo(gethostname(),None)# print(gethostname())# 設置連接服務端被分配到的IP地址print("開始掃描服務器")# 分配主機號為100~254for i in range(100, 254):client=socket(AF_INET,SOCK_STREAM)# 設置套接字對象地址可復用client.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)# 設置套接字對象超時時間client.settimeout(1)temp="192.168.189.%s" %itry:# 連接服務端,若成功則返回0data=client.connect_ex((temp,7788))if data==0:print("找到服務器")# 設置是否連接服務器p=input("是否連接:y/n")# 若連接則將分配到的IP傳入客戶端if p=='y':ip=tempbreak# 若不連接則跳到程序結束關閉套接字else:continueexcept:print("error")# 關閉客戶端套接字client.close()# 若未分配到IP地址則連接失敗結束程序if ip=="":print("未連接成功服務器")sys.exit()# 開啟客戶端套接字client=socket(AF_INET,SOCK_STREAM)try:client.connect((ip,7788))running=True# 創建兩個線程,t1用于發送數據,t1用于接收數據t2=Thread(target=send,args=(client,))t1=Thread(target=recv,args=(client,t2))t1.start()t1.join()t2.join()# 若有錯誤就調至finallyexcept:passfinally:# 關閉客戶端套接字print("連接關閉")client.close()TCP客戶端
剛學完套接字(socket),寫了一個聊天室,用函數寫了一個以后就研究了一下怎么用面向對象的方式寫了一個,可能會有點問題,希望大佬指點一下
總結
以上是生活随笔為你收集整理的使用python基于socket的tcp服务器聊天室的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C#-初识Hangfire
- 下一篇: GitHub——修改DNS提高git c