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


Posted in Python onSeptember 14, 2017

后续代码更新和功能添加会提交到个人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()

运行结果示例

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

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

客户端1:

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

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

客户端2:

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

客户端3:

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

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

Python 相关文章推荐
python中的yield使用方法
Feb 11 Python
使用Python下载歌词并嵌入歌曲文件中的实现代码
Nov 13 Python
python中函数传参详解
Jul 03 Python
django实现前后台交互实例
Aug 07 Python
python的构建工具setup.py的方法使用示例
Oct 23 Python
在python win系统下 打开TXT文件的实例
Apr 29 Python
Django migrations 默认目录修改的方法教程
Sep 28 Python
pyecharts调整图例与各板块的位置间距实例
May 16 Python
Python内置异常类型全面汇总
May 28 Python
关于python的缩进规则的知识点详解
Jun 22 Python
使用Python实现音频双通道分离
Dec 25 Python
python函数的两种嵌套方法使用
Apr 02 Python
Python实现购物系统(示例讲解)
Sep 13 #Python
python模块之sys模块和序列化模块(实例讲解)
Sep 13 #Python
python模块之time模块(实例讲解)
Sep 13 #Python
python difflib模块示例讲解
Sep 13 #Python
Python网络编程 Python套接字编程
Sep 13 #Python
python和ruby,我选谁?
Sep 13 #Python
python实现简单点对点(p2p)聊天
Sep 13 #Python
You might like
Smarty Foreach 使用说明
2010/03/23 PHP
php魔法函数与魔法常量使用介绍
2017/07/23 PHP
PHP实现断点续传乱序合并文件的方法
2018/09/06 PHP
PHP实现PDO操作mysql存储过程示例
2019/02/13 PHP
Laravel 模型使用软删除-左连接查询-表起别名示例
2019/10/24 PHP
一些常用的JavaScript函数(json)附详细说明
2011/05/25 Javascript
jquery制作搜狐快站页面效果示例分享
2014/02/21 Javascript
javascript作用域链(Scope Chain)用法实例解析
2015/11/30 Javascript
js实现瀑布流的三种方式比较
2020/06/28 Javascript
js返回顶部实例分享
2016/12/21 Javascript
原生js实现网页顶部自动下拉/收缩广告效果
2017/01/20 Javascript
JavaScript学习笔记之惰性函数示例详解
2017/08/27 Javascript
jQuery实现的弹幕效果完整实例
2017/09/06 jQuery
Node.js对MongoDB进行增删改查操作的实例代码
2019/04/18 Javascript
[53:15]Mineski vs iG 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
python计算两个矩形框重合百分比的实例
2018/11/07 Python
python-opencv颜色提取分割方法
2018/12/08 Python
对python for 文件指定行读写操作详解
2018/12/29 Python
Python利用字典破解WIFI密码的方法
2019/02/27 Python
python绘制彩虹图
2019/12/16 Python
计算Python Numpy向量之间的欧氏距离实例
2020/05/22 Python
浅析移动设备HTML5页面布局
2015/12/01 HTML / CSS
英国工艺品购物网站:Minerva Crafts
2018/01/29 全球购物
高中毕业生生活的自我评价
2013/12/08 职场文书
酒店司机岗位职责
2013/12/14 职场文书
大学生职业生涯规划书模版
2013/12/30 职场文书
幼儿教师研修感言
2014/02/12 职场文书
反邪教宣传工作方案
2014/05/07 职场文书
竞选班干部演讲稿100字
2014/08/20 职场文书
立志成才演讲稿
2014/09/04 职场文书
2014法院干警廉洁警示教育思想汇报
2014/09/13 职场文书
离婚协议书怎么写
2015/01/26 职场文书
新人入职感言
2015/07/31 职场文书
西部计划志愿者工作总结
2015/08/11 职场文书
历史名人教你十五个读书方法,赶快Get起来!
2019/07/18 职场文书
PyQt5 QThread倒计时功能的实现代码
2021/04/02 Python