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模拟实现POST请求提交图片的方法
Jul 25 Python
python破解zip加密文件的方法
May 31 Python
浅谈Python 多进程默认不能共享全局变量的问题
Jan 11 Python
Pycharm 字体大小调整设置的方法实现
Sep 27 Python
pytorch 状态字典:state_dict使用详解
Jan 17 Python
Python3 io文本及原始流I/O工具用法详解
Mar 23 Python
Python垃圾回收机制三种实现方法
Apr 27 Python
详解python中groupby函数通俗易懂
May 14 Python
pycharm + django跨域无提示的解决方法
Dec 06 Python
python中numpy.empty()函数实例讲解
Feb 05 Python
Python第三方库安装缓慢的解决方法
Feb 06 Python
Python使用sql语句对mysql数据库多条件模糊查询的思路详解
Apr 12 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
浅析PKI加密解密 OpenSSL
2013/07/01 PHP
php5.3提示Function ereg() is deprecated Error问题解决方法
2014/11/12 PHP
Yii中的relations数据关联查询及统计功能用法详解
2016/07/14 PHP
PHP简单数据库操作类实例【支持增删改查及链式操作】
2016/10/10 PHP
基于jquery1.4.2的仿flash超炫焦点图播放效果
2010/04/20 Javascript
基于jquery的让页面控件不可用的实现代码
2010/04/27 Javascript
JavaScript去掉数组中的重复元素
2011/01/13 Javascript
jQuery学习总结之元素的相对定位和选择器(持续更新)
2011/04/26 Javascript
基于jQuery的输入框在光标位置插入内容, 并选中
2011/10/29 Javascript
在服务端(Page.Write)调用自定义的JS方法详解
2013/08/09 Javascript
快速解决FusionCharts联动的中文乱码问题
2013/12/04 Javascript
学习JavaScript设计模式(链式调用)
2015/11/26 Javascript
JQuery实现Ajax加载图片的方法
2015/12/24 Javascript
JS基于for语句编写的九九乘法表示例
2018/01/04 Javascript
vue中阻止click事件冒泡,防止触发另一个事件的方法
2018/02/08 Javascript
使用JQuery自动完成插件Auto Complete详解
2019/06/18 jQuery
JavaScript中的this妙用实例分析
2020/05/09 Javascript
[01:32]DOTA2上海特锦赛现场采访:最想COS的英雄
2016/03/25 DOTA
[01:03:09]完美世界DOTA2联赛PWL S2 Forest vs SZ 第二场 11.25
2020/11/26 DOTA
python版简单工厂模式
2017/10/16 Python
Python基于property实现类的特性操作示例
2018/06/15 Python
Pyqt5 基本界面组件之inputDialog的使用
2019/06/25 Python
python自定义时钟类、定时任务类
2021/02/22 Python
基于python实现模拟数据结构模型
2020/06/12 Python
Selenium+BeautifulSoup+json获取Script标签内的json数据
2020/12/07 Python
CSS3实现红包抖动效果
2020/12/23 HTML / CSS
Html5饼图绘制实现统计图的方法
2020/08/05 HTML / CSS
ivx平台开发之不用代码实现一个九宫格抽奖功能
2021/01/27 HTML / CSS
Laura Mercier官网:彩妆大师罗拉玛斯亚的化妆品牌
2018/01/04 全球购物
Diptyque英国官方网站:源自法国的知名香氛品牌
2019/08/28 全球购物
法国购买隐形眼镜和眼镜网站:Optical Center
2019/10/08 全球购物
汉语言文学职业规划
2014/02/14 职场文书
倡议书的写法
2014/08/30 职场文书
大学生万能检讨书范例
2014/10/04 职场文书
暗恋桃花源观后感
2015/06/12 职场文书
教师读书笔记
2015/06/29 职场文书