网络编程
位置:首页>> 网络编程>> Python编程>> python实现简单聊天应用 python群聊和点对点均实现

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

作者:Lockeyi  发布时间:2023-01-16 08:35:55 

标签:python,聊天应用,点对点

后续代码更新和功能添加会提交到个人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 'c * Cpcp':
  #进入个人聊天
   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)!!!

来源:http://blog.csdn.net/Lockey23/article/details/77940518

0
投稿

猜你喜欢

  • Overview这篇博客内容将包括对XML文件的解析、追加新元素后写入到XML,以及更新原XML文件中某结点的值。使用的是python的xm
  • 使用python实现简单倒计时exe,供大家参考,具体内容如下使用tkinter制作界面实现倒计时功能。使用time.sleep(1)实现
  • 在这篇文章(不敢妄称教程,最多称之为学习笔记)里,我会从头开始实现客户端模板的效果。不过你不要期望能够在这里找到可以直接拿去使用直接复用灵活
  • 今天要处理通知书上的日期,写的一个处理程序,效率可能不是最优的,不过实现功能绝对没问题。注:月份和天要分>10,=10,<10三
  • scrapy框架概述:Scrapy,Python开发的一个快速,高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数
  • 用flask时遇到了返回字符串支持中文显示的问题,在web端显示的是utf-8的编码,而不是中文,如下图。虽然不影响接口的读取,但是可读性太
  • 引子Tornado 是一个网络异步的的web开发框架, 并且可以利用多进程进行提高效率, 下面是创建一个多进程 tornado 程序的例子.
  • 本文实例为大家分享了python将两张图片生成全景图片的具体代码,供大家参考,具体内容如下1、全景图片的介绍全景图通过广角的表现手段以及绘画
  • Python里的正则表达式Python里的正则表达式,无需下载外部模块,只需要引入自带模块:re:import re官方re模块文档: ht
  • 译者按:在iOS HIG已经强大经典了N年之后,Android终于推出了一套比较系统的HIG(大概是为了配合Android 4.0 Ice
  • 在Python中,很多对象都是可以通过for语句来直接遍历的,例如list、string、dict等等,这些对象都可以被称为可迭代对象。至于
  • python爬虫用mongodb的原因:1、文档结构的存储方式简单讲就是可以直接存json,list2、不要事先定义”表”,随时可以创建3、
  • 问一下谁知道如何用 javascript 获取硬盘信息1.获得硬盘当前有几个盘符.2.每个盘符的 大小,已经使用的大小,和没有使用的大小原理
  • 本书的作者Douglas Crockford是JavaScript开发社区最知名的权威,JavaScript的发明人Brendan Eich
  • 迭代器是一种支持next()操作的对象。它包含一组元素,当执行next()操作时,返回其中一个元素;当所有元素都被返回后,生成一个StopI
  • 构筑专业的网络站点和应用程序,先进的设计工具,功能强大,开放式集成系统;流畅的开发进程。Macromedia Dreamweaver MX
  • Fib实例虽然能作用于for循环,看起来和list有点像,但是,把它当成list来使用还是不行,比如,取第5个元素:>>>
  • 光学元件类平面反射镜是一种极为简单的模型,因为我们只需要考虑一个平面即可。但是除此之外的其他光学元件,可能会变得有些复杂:我们必须考虑光在入
  • asp编程手工定义参数的方法:  Dim con As ADODB.Connection 
  • 有时我们需要较为实时的查看服务器上的网卡流量,这里我写了两个小脚本,一个用shell(先写的,一次只能查看一个网卡),另一个用Python(
手机版 网络编程 asp之家 www.aspxhome.com