python實(shí)現(xiàn)簡(jiǎn)單聊天應(yīng)用 python群聊和點(diǎn)對(duì)點(diǎn)均實(shí)現(xiàn)
后續(xù)代碼更新和功能添加會(huì)提交到個(gè)人github主頁(yè),有興趣可以一起來(lái)完善!
如果只是拿過(guò)去運(yùn)行看結(jié)果,請(qǐng)注意平臺(tái)相關(guān)性以及python版本號(hào),本示例開(kāi)發(fā)運(yùn)行平臺(tái)為win7x86_64 pycharm community,python版本號(hào)為3.5!!!
TALK IS CHEAP, SHOW YOU MY CODE:
客戶端
#coding:utf-8
'''
file:client.py.py
date:2017/9/11 11:01
author:lockey
email:lockey@123.com
platform:win7.x86_64 pycharm python3
desc:p2p communication clientside
'''
from socket import *
import threading,sys,json,re
#引入json模塊主要是為了數(shù)據(jù)的封裝傳輸,re的話是做一些合法性的驗(yàn)證
HOST = '192.168.1.7'
PORT=8022
BUFSIZE = 1024 ##緩沖區(qū)大小 1K
ADDR = (HOST,PORT)
myre = r"^[_a-zA-Z]\w{0,}"
tcpCliSock = socket(AF_INET,SOCK_STREAM)
#創(chuàng)建一個(gè)socket連接
userAccount = None
#用戶登錄標(biāo)志,也用來(lái)記錄登錄的用戶名稱
def register():
#用戶注冊(cè)函數(shù)
print("""
Glad to have you a member of us!
""")
accout = input('Please input your account: ')
if not re.findall(myre, accout):
print('Account illegal!')
return None
password1 = input('Please input your password: ')
password2 = input('Please confirm your password: ')
if not (password1 and password1 == password2):
print('Password not illegal!')
return None
global userAccount
userAccount = accout
regInfo = [accout,password1,'register']
datastr = json.dumps(regInfo)
tcpCliSock.send(datastr.encode('utf-8'))
data = tcpCliSock.recv(BUFSIZE)
data = data.decode('utf-8')
if data == '0':
print('Success to register!')
return True
elif data == '1':
print('Failed to register, account existed!')
return False
else:
print('Failed for exceptions!')
return False
def login():
#用戶登錄函數(shù)
print("""
Welcome to login in!
""")
accout = input('Account: ')
if not re.findall(myre, accout):
print('Account illegal!')
return None
password = input('Password: ')
if not password:
print('Password illegal!')
return None
global userAccount
userAccount = accout
loginInfo = [accout, password,'login']
datastr = json.dumps(loginInfo)
tcpCliSock.send(datastr.encode('utf-8'))
data = tcpCliSock.recv(BUFSIZE)
if data == '0':
print('Success to login!')
return True
else:
print('Failed to login in(user not exist or username not match the password)!')
return False
def addGroup():
#群組添加
groupname = input('Please input group name: ')
if not re.findall(myre, groupname):
print('group name illegal!')
return None
return groupname
def chat(target):
#進(jìn)入聊天(群聊和點(diǎn)對(duì)點(diǎn)聊天可以選擇)
while True:
print('{} -> {}: '.format(userAccount,target))
msg = input()
if len(msg) > 0 and not msg in 'qQ':
if 'group' in target:
optype = 'cg'
else:
optype = 'cp'
dataObj = {'type': optype, 'to': target, 'msg': msg, 'froms': userAccount}
datastr = json.dumps(dataObj)
tcpCliSock.send(datastr.encode('utf-8'))
continue
elif msg in 'qQ':
break
else:
print('Send data illegal!')
class inputdata(threading.Thread):
#用戶輸入選擇然后執(zhí)行不同的功能程序
def run(self):
menu = """
(CP): Chat with individual
(CG): Chat with group member
(AG): Add a group
(EG): Enter a group
(H): For help menu
(Q): Quit the system
"""
print(menu)
while True:
operation = input('Please input your operation("h" for help): ')
if operation in 'cPCPCpcp':
#進(jìn)入個(gè)人聊天
target = input('Who would you like to chat with: ')
chat(target)
continue
if operation in 'cgCGCgcG':
#進(jìn)入群聊
target = input('Which group would you like to chat with: ')
chat('group'+target)
continue
if operation in 'agAGAgaG':
#添加群組
groupName = addGroup()
if groupName:
dataObj = {'type': 'ag', 'groupName': groupName}
dataObj = json.dumps(dataObj)
tcpCliSock.send(dataObj.encode('utf-8'))
continue
if operation in 'egEGEgeG':
#入群
groupname = input('Please input group name fro entering: ')
if not re.findall(myre, groupname):
print('group name illegal!')
return None
dataObj = {'type': 'eg', 'groupName': 'group'+groupname}
dataObj = json.dumps(dataObj)
tcpCliSock.send(dataObj.encode('utf-8'))
continue
if operation in 'hH':
print(menu)
continue
if operation in 'qQ':
sys.exit(1)
else:
print('No such operation!')
class getdata(threading.Thread):
#接收數(shù)據(jù)線程
def run(self):
while True:
data = tcpCliSock.recv(BUFSIZE).decode('utf-8')
if data == '-1':
print('can not connect to target!')
continue
if data == 'ag0':
print('Group added!')
continue
if data == 'eg0':
print('Entered group!')
continue
if data == 'eg1':
print('Failed to enter group!')
continue
dataObj = json.loads(data)
if dataObj['type'] == 'cg':
#群組消息的格式定義
print('{}(from {})-> : {}'.format(dataObj['froms'], dataObj['to'], dataObj['msg']))
else:
#個(gè)人消息的格式定義
print('{} ->{} : {}'.format(dataObj['froms'], userAccount, dataObj['msg']))
def main():
try:
tcpCliSock.connect(ADDR)
print('Connected with server')
while True:
loginorReg = input('(l)ogin or (r)egister a new account: ')
if loginorReg in 'lL':
log = login()
if log:
break
if loginorReg in 'rR':
reg = register()
if reg:
break
myinputd = inputdata()
mygetdata = getdata()
myinputd.start()
mygetdata.start()
myinputd.join()
mygetdata.join()
except Exception:
print('error')
tcpCliSock.close()
sys.exit()
if __name__ == '__main__':
main()
服務(wù)端
#coding:utf-8
'''
file:server.py
date:2017/9/11 14:43
author:lockey
email:lockey@123.com
platform:win7.x86_64 pycharm python3
desc:p2p communication serverside
'''
import socketserver,json,time
import subprocess
connLst = []
groupLst = []
## 代號(hào) 地址和端口 連接對(duì)象
#optype = {'ag':'group adding','cp':'chat with individual','cg':'chat with group'}
class Connector(object): ##連接對(duì)象類
def __init__(self,account,password,addrPort,conObj):
self.account = account
self.password = password
self.addrPort = addrPort
self.conObj = conObj
class Group(object):#群組類
def __init__(self,groupname,groupOwner):
self.groupId = 'group'+str(len(groupLst)+1)
self.groupName = 'group'+groupname
self.groupOwner = groupOwner
self.createTime = time.time()
self.members=[groupOwner]
class MyServer(socketserver.BaseRequestHandler):
def handle(self):
print("got connection from",self.client_address)
userIn = False
global connLst
global groupLst
while not userIn:
conn = self.request
data = conn.recv(1024)
if not data:
continue
dataobj = json.loads(data.decode('utf-8'))
#如果連接客戶端發(fā)送過(guò)來(lái)的信息格式是一個(gè)列表且注冊(cè)標(biāo)識(shí)為False時(shí)進(jìn)行用戶注冊(cè)或者登陸
ret = '0'
if type(dataobj) == list and not userIn:
account = dataobj[0]
password = dataobj[1]
optype = dataobj[2]
existuser = False
if len(connLst) > 0:
for obj in connLst:
if obj.account == account:
existuser = True
if obj.password == password:
userIn = True
print('{} has logged in system({})'.format(account,self.client_address))
break
if optype == 'login' and (not userIn or not existuser):
ret = '1'
print('{} failed to logged in system({})'.format(account, self.client_address))
else:
if existuser:
ret = '1'
print('{} failed to register({}),account existed!'.format(account, self.client_address))
else:
try:
conObj = Connector(account,password,self.client_address,self.request)
connLst.append(conObj)
print('{} has registered to system({})'.format(account,self.client_address))
userIn = True
except:
print('%s failed to register for exception!'%account)
ret = '99'
conn.sendall(ret.encode('utf-8'))
if ret == '0':
break
while True:
#除登陸注冊(cè)之外的請(qǐng)求的監(jiān)聽(tīng)
conn = self.request
data = conn.recv(1024)
if not data:
continue
print(data)
dataobj = data.decode('utf-8')
dataobj = json.loads(dataobj)
if dataobj['type'] == 'ag' and userIn:
#如果判斷用戶操作請(qǐng)求類型為添加群組則進(jìn)行以下操作
groupName = dataobj['groupName']
groupObj = Group(groupName,self.request)
groupLst.append(groupObj)
conn.sendall('ag0'.encode('utf-8'))
print('%s added'%groupName)
continue
if dataobj['type'] == 'eg' and userIn:
#入群操作
groupName = dataobj['groupName']
ret = 'eg1'
for group in groupLst:
if groupName == group.groupName:
group.members.append(self.request)
print('{} added into {}'.format(self.client_address,groupName))
ret = 'eg0'
break
conn.sendall(ret.encode('utf-8'))
continue
#客戶端將數(shù)據(jù)發(fā)給服務(wù)器端然后由服務(wù)器轉(zhuǎn)發(fā)給目標(biāo)客戶端
print('connLst',connLst)
print('grouplst',groupLst)
if len(connLst) > 1:
sendok = False
if dataobj['type'] == 'cg':
#群內(nèi)廣播(除發(fā)消息的人)
print('group',data)
for obj in groupLst:
if obj.groupName == dataobj['to']:
for user in obj.members:
if user != self.request:
user.sendall(data)
else:
#個(gè)人信息發(fā)送
for obj in connLst:
if dataobj['to'] == obj.account:
obj.conObj.sendall(data)
sendok = True
if sendok == False:
print('no target valid!')
else:
conn.sendall('-1'.encode('utf-8'))
continue
if __name__ == '__main__':
server = socketserver.ThreadingTCPServer(('192.168.1.7',8022),MyServer)
print('waiting for connection...')
server.serve_forever()
運(yùn)行結(jié)果示例
服務(wù)端(記錄著各客戶端的操作):

客戶端1:
有注冊(cè)、建群、群聊、點(diǎn)對(duì)點(diǎn)聊天

客戶端2:

客戶端3:

要拷貝代碼運(yùn)行的話請(qǐng)注意平臺(tái)(win7.x86_64)和python版本號(hào)(python3.5)?。?!
相關(guān)文章
python安裝后無(wú)法打開(kāi)IDLE?Subprocess?Connection?Error的解決方法
有朋友在安裝了Python之后發(fā)現(xiàn)不能正常使用,就說(shuō)明安裝過(guò)程出了問(wèn)題,下面這篇文章主要給大家介紹了關(guān)于python安裝后無(wú)法打開(kāi)IDLE?Subprocess?Connection?Error的解決方法,需要的朋友可以參考下2023-01-01
Django開(kāi)發(fā)web后端對(duì)比SpringBoot示例分析
這篇文章主要介紹了Django開(kāi)發(fā)web后端對(duì)比SpringBoot示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12
python利用appium實(shí)現(xiàn)手機(jī)APP自動(dòng)化的示例
這篇文章主要介紹了python利用appium實(shí)現(xiàn)手機(jī)APP自動(dòng)化的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
python中redis查看剩余過(guò)期時(shí)間及用正則通配符批量刪除key的方法
這篇文章主要介紹了python中redis查看剩余過(guò)期時(shí)間及用正則通配符批量刪除key的方法,需要的朋友可以參考下2018-07-07
基于python+selenium自動(dòng)健康打卡的實(shí)現(xiàn)代碼
這篇文章主要介紹了基于python+selenium自動(dòng)健康打卡,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
PYTHON基礎(chǔ)-時(shí)間日期處理小結(jié)
PYTHON時(shí)間日期處理函數(shù)以datetime為中心, 起點(diǎn)或中轉(zhuǎn), 轉(zhuǎn)化為目標(biāo)對(duì)象, 涵蓋了大多數(shù)業(yè)務(wù)場(chǎng)景中需要的日期轉(zhuǎn)換處理,這里就為大家介紹一下,需要的朋友可以參考下2018-05-05

