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网络编程学习笔记(五):socket的一些补充
Jun 09 Python
TensorFlow变量管理详解
Mar 10 Python
tensorflow获取变量维度信息
Mar 10 Python
Python OpenCV处理图像之图像直方图和反向投影
Jul 10 Python
Python 通过调用接口获取公交信息的实例
Dec 17 Python
Python初学者常见错误详解
Jul 02 Python
Python 占位符的使用方法详解
Jul 10 Python
python3.x提取中文的正则表达式示例代码
Jul 23 Python
利用django创建一个简易的博客网站的示例
Sep 29 Python
为2021年的第一场雪锦上添花:用matplotlib绘制雪花和雪景
Jan 05 Python
详解Django中的FBV和CBV对比分析
Mar 01 Python
python抢购软件/插件/脚本附完整源码
Mar 04 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
PHP入门之常量简介和系统常量
2014/05/12 PHP
VB中的RasEnumConnections函数返回632错误解决方法
2014/07/29 PHP
PHP的Socket通信之UDP通信实例
2015/07/02 PHP
Thinkphp结合AJAX长轮询实现PC与APP推送详解
2017/07/31 PHP
自写简单JS判断是否已经弹出页面
2010/10/20 Javascript
jquery入门——事件机制之事件中的冒泡现象示例解释
2020/09/12 Javascript
javascript用函数实现对象的方法
2015/05/14 Javascript
程序员必知35个jQuery 代码片段
2015/11/05 Javascript
基于jQuery Tipso插件实现消息提示框特效
2016/03/16 Javascript
jQuery插件HighCharts实现的2D条状图效果示例【附demo源码下载】
2017/03/15 Javascript
基于zepto.js实现登录界面
2017/10/09 Javascript
Vuerouter的beforeEach与afterEach钩子函数的区别
2018/12/26 Javascript
JavaScript实现的开关灯泡点击切换特效示例
2019/07/08 Javascript
Layui 导航默认展开和菜单栏选中高亮设置的方法
2019/09/04 Javascript
小程序使用分包的示例代码
2020/03/23 Javascript
Python中的测试模块unittest和doctest的使用教程
2015/04/14 Python
Python中的choice()方法使用详解
2015/05/15 Python
ubuntu安装sublime3并配置python3环境的方法
2018/03/15 Python
python 基本数据类型占用内存空间大小的实例
2018/06/12 Python
Pycharm中import torch报错的快速解决方法
2020/03/05 Python
python+selenium+Chrome options参数的使用
2020/03/18 Python
在Sublime Editor中配置Python环境的详细教程
2020/05/03 Python
python两种获取剪贴板内容的方法
2020/11/06 Python
Matlab使用Plot函数实现数据动态显示方法总结
2021/02/25 Python
HTML5 DeviceOrientation实现手机网站摇一摇功能代码实例
2015/04/24 HTML / CSS
Vans英国官方网站:美国南加州的原创极限运动潮牌
2017/01/20 全球购物
管理部部长岗位职责
2013/12/05 职场文书
大学生的应聘自我评价
2013/12/13 职场文书
法务专员岗位职责
2014/01/02 职场文书
五星级酒店餐饮部总监的标准岗位职责
2014/02/17 职场文书
2014年幼儿园植树节活动方案
2014/03/02 职场文书
小学国庆节活动总结
2015/03/23 职场文书
单位收入证明范本
2015/06/18 职场文书
安全生产感想
2015/08/07 职场文书
CSS实现切角+边框+投影+内容背景色渐变效果
2021/11/01 HTML / CSS
python实现双向链表原理
2022/05/25 Python