python实现简单聊天应用 python群聊和点对点均实现

后续代码更新和功能添加会提交到 个人github主页 ,有兴趣可以一起来完善!

如果只是拿过去运行看结果,请注意平台相关性以及python版本号,本示例开发运行平台为win7x86_64 pycharm community,python版本号为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模块主要是为了数据的封装传输,re的话是做一些合法性的验证
   HOST = '192.168.1.7'
   PORT=8022
   BUFSIZE = 1024 ##缓冲区大小 1K
   ADDR = (HOST,PORT)
   myre = r"^[_a-zA-Z]\w{0,}"
   tcpCliSock = socket(AF_INET,SOCK_STREAM)
   #创建一个socket连接
   userAccount = None
   #用户登录标志,也用来记录登录的用户名称
   def register():
   #用户注册函数
    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():
   #用户登录函数
    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):
   #进入聊天(群聊和点对点聊天可以选择)
    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):
   #用户输入选择然后执行不同的功能程序
    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':
      #进入个人聊天
       target = input('Who would you like to chat with: ')
       chat(target)
       continue
   
      if operation in 'cgCGCgcG':
      #进入群聊
       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):
   #接收数据线程
    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:
      #个人消息的格式定义
       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()
   
   

服务端


   #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 = []
   ## 代号 地址和端口 连接对象
   #optype = {'ag':'group adding','cp':'chat with individual','cg':'chat with group'}
   class Connector(object): ##连接对象类
    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'))
      #如果连接客户端发送过来的信息格式是一个列表且注册标识为False时进行用户注册或者登陆
      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:
     #除登陆注册之外的请求的监听
      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:
      #如果判断用户操作请求类型为添加群组则进行以下操作
       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
   
      #客户端将数据发给服务器端然后由服务器转发给目标客户端
      print('connLst',connLst)
      print('grouplst',groupLst)
      if len(connLst) > 1:
       sendok = False
       if dataobj['type'] == 'cg':
       #群内广播(除发消息的人)
        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:
       #个人信息发送
        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()
   
   

运行结果示例

服务端(记录着各客户端的操作):

这里写图片描述

客户端1:

有注册、建群、群聊、点对点聊天

这里写图片描述

客户端2:

这里写图片描述

客户端3:

这里写图片描述

要拷贝代码运行的话请注意平台(win7.x86_64)和python版本号(python3.5)!!!

 

posted on 2021-06-22 14:49  BabyGo000  阅读(101)  评论(0)    收藏  举报