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

Posted BabyGo000

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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)!!!

 

以上是关于python实现简单聊天应用 python群聊和点对点均实现的主要内容,如果未能解决你的问题,请参考以下文章

Netty网络聊天 聊天室实战

Flask 实现 WebSocket 通讯---群聊和私聊

微信聊天的长连设计探讨之负载均衡

使用Nio实现一个简易的群聊和单聊

websocket实现群聊和单聊(转)

javascript基于websocketnodejsuniapp的聊天室