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实现的检测网站挂马程序
Nov 30 Python
Python多线程编程(六):可重入锁RLock
Apr 05 Python
Python通过select实现异步IO的方法
Jun 04 Python
python实现多线程的方式及多条命令并发执行
Jun 07 Python
Python中的左斜杠、右斜杠(正斜杠和反斜杠)
Aug 30 Python
详解MySQL数据类型int(M)中M的含义
Nov 20 Python
python实现学生管理系统
Jan 11 Python
python3 破解 geetest(极验)的滑块验证码功能
Feb 24 Python
Python类的继承、多态及获取对象信息操作详解
Feb 28 Python
Flask之pipenv虚拟环境的实现
Nov 26 Python
python学生管理系统的实现
Apr 05 Python
python3中数组逆序输出方法
Dec 01 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
对盗链说再见...
2006/10/09 PHP
获取PHP警告错误信息的解决方法
2013/06/03 PHP
ThinkPHP3.2.2的插件控制器功能简述
2014/07/09 PHP
PHP去掉json字符串中的反斜杠\及去掉双引号前的反斜杠
2015/09/30 PHP
php curl上传、下载、https登陆实现代码
2017/07/23 PHP
PHP读取word文档的方法分析【基于COM组件】
2017/08/01 PHP
PHP实现redis限制单ip、单用户的访问次数功能示例
2018/06/16 PHP
js实现iframe动态调整高度的代码
2008/01/06 Javascript
用JavaScript调用WebService的示例
2008/04/07 Javascript
基于jQuery的淡入淡出可自动切换的幻灯插件打包下载
2010/09/15 Javascript
JavaScript Scoping and Hoisting 翻译
2012/07/03 Javascript
JS跨域代码片段
2012/08/30 Javascript
javascript的解析执行顺序在各个浏览器中的不同
2014/03/17 Javascript
jQuery自动添加表单项的方法
2015/07/13 Javascript
js实现微信分享代码
2020/10/11 Javascript
Node.js刷新session过期时间的实现方法推荐
2016/05/18 Javascript
Javascript 正则表达式校验数字的简单实例
2016/11/02 Javascript
node内置调试方法总结
2018/02/22 Javascript
node 命令方式启动修改端口的方法
2018/05/12 Javascript
vuejs 动态添加input框的实例讲解
2018/08/24 Javascript
nodejs基础之buffer缓冲区用法分析
2018/12/26 NodeJs
解决layui 三级联动下拉框更新时回显的问题
2019/09/03 Javascript
vue.js路由mode配置之去掉url上默认的#方法
2019/11/01 Javascript
vue+elementUI动态增加表单项并添加验证的代码详解
2020/12/17 Vue.js
原生js实现滑块区间组件
2021/01/20 Javascript
Python选择排序、冒泡排序、合并排序代码实例
2015/04/10 Python
windows下python 3.6.4安装配置图文教程
2018/08/21 Python
Links of London官方网站:英国标志性的珠宝品牌
2017/04/09 全球购物
简历中自我评价怎么写
2014/02/12 职场文书
班主任经验交流会主持词
2014/04/01 职场文书
身边的榜样活动方案
2014/08/20 职场文书
小学教师岗位职责
2015/04/02 职场文书
罚款通知怎么写
2015/04/22 职场文书
蜗居观后感
2015/06/11 职场文书
基于Python绘制子图及子图刻度的变换等的问题
2021/05/23 Python
javascript代码简写的几种常用方式汇总
2021/08/23 Javascript