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多进程multiprocessing用法实例分析
Aug 18 Python
用Python将结果保存为xlsx的方法
Jan 28 Python
python学生管理系统学习笔记
Mar 19 Python
Python shelve模块实现解析
Aug 28 Python
使用celery和Django处理异步任务的流程分析
Feb 19 Python
Python实现病毒仿真器的方法示例(附demo)
Feb 19 Python
python3将变量写入SQL语句的实现方式
Mar 02 Python
Python Opencv 通过轨迹(跟踪)栏实现更改整张图像的背景颜色
Mar 09 Python
python网络编程:socketserver的基本使用方法实例分析
Apr 09 Python
keras.layer.input()用法说明
Jun 16 Python
python名片管理系统开发
Jun 18 Python
Python数据可视化之Seaborn的安装及使用
Apr 19 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
Yii2使用小技巧之通过 Composer 添加 FontAwesome 字体资源
2014/06/22 PHP
PHP + plupload.js实现多图上传并显示进度条加删除实例代码
2017/03/06 PHP
javascript实现简单的省市区三级联动
2015/05/14 Javascript
javascript精确统计网站访问量实例代码
2015/12/19 Javascript
基于jquery实现鼠标左右拖动滑块滑动附源码下载
2015/12/23 Javascript
javascript实现的猜数小游戏完整实例代码
2016/05/10 Javascript
Javascript将数值转换为金额格式(分隔千分位和自动增加小数点)
2016/06/22 Javascript
js无提示关闭浏览器窗口的两种方法分析
2016/11/06 Javascript
完全深入学习Bootstrap表单
2016/11/28 Javascript
JavaScript用构造函数如何获取变量的类型名
2016/12/23 Javascript
js处理层级数据结构的方法小结
2017/01/17 Javascript
JS实现隔行换色的表格排序
2017/03/27 Javascript
NodeJS 实现手机短信验证模块阿里大于功能
2017/06/19 NodeJs
jQuery实现frame之间互通的方法
2017/06/26 jQuery
微信小程序三级联动地址选择器的实例代码
2017/07/12 Javascript
JS实现电商放大镜效果
2017/08/24 Javascript
vue实现鼠标经过动画
2019/10/16 Javascript
vue封装可复用组件confirm,并绑定在vue原型上的示例
2019/10/31 Javascript
vue实现页面切换滑动效果
2020/06/29 Javascript
vue-cli或vue项目利用HBuilder打包成移动端app操作
2020/07/29 Javascript
在Python中使用defaultdict初始化字典以及应用方法
2018/10/31 Python
tensor和numpy的互相转换的实现示例
2019/08/02 Python
python实现网站用户名密码自动登录功能
2019/08/09 Python
Python中最好用的命令行参数解析工具(argparse)
2019/08/23 Python
pytorch 实现模型不同层设置不同的学习率方式
2020/01/06 Python
Anaconda+vscode+pytorch环境搭建过程详解
2020/05/25 Python
神经网络训练采用gpu设置的方式
2021/03/03 Python
国外最大的眼镜网站:Coastal
2017/08/09 全球购物
俄罗斯厨房产品购物网站:COOK HOUSE
2021/03/15 全球购物
八年级历史教学反思
2014/01/10 职场文书
感恩教育活动总结
2014/05/05 职场文书
新学期国旗下演讲稿
2014/05/08 职场文书
校车安全管理责任书
2015/05/11 职场文书
2015年外贸业务员工作总结范文
2015/05/23 职场文书
教你用python控制安卓手机
2021/05/13 Python
JavaScript中的LHS和RHS分析详情
2022/04/06 Javascript