python简单聊天功能 python实现简单聊天应用(群聊和点对点均实现)

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

<div class="article-info-box">
    <div class="article-bar-top d-flex">
                                            <span class="time">2017年09月12日 00:45:48</span>
        <div class="float-right">
            <span class="read-count">阅读数:2640</span>
                                        </div>
    </div>
</div>
<article>
    <div id="article_content" class="article_content clearfix csdn-tracking-statistics" data-pid="blog" data-mod="popu_307" data-dsm="post">
                <div class="markdown_views">
            <p>后续代码更新和功能添加会提交到<a href="https://github.com/LockeyCheng/python-p2p-chating/tree/master" rel="nofollow" target="_blank">个人github主页</a>,有兴趣可以一起来完善!</p>

如果只是拿过去运行看结果,请注意平台相关性以及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:[email protected]
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()
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217

服务端

#coding:utf-8
'''
file:server.py
date:2017/9/11 14:43
author:lockey
email:[email protected]
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()
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139

运行结果示例

服务端(记录着各客户端的操作):
这里写图片描述

客户端1:
有注册、建群、群聊、点对点聊天
这里写图片描述

客户端2:
这里写图片描述

客户端3:
这里写图片描述

要拷贝代码运行的话请注意平台(win7.x86_64)和python版本号(python3.5)!!!




    <div class="article-bar-bottom">
            <div class="article-copyright">
        版权声明:本文为博主原创文章,未经博主允许不得转载。          https://blog.csdn.net/Lockey23/article/details/77940518     </div>
                    <div class="tags-box artic-tag-box">
        <span class="label">文章标签:</span>
                    <a data-track-click="{&quot;mod&quot;:&quot;popu_626&quot;,&quot;con&quot;:&quot;python网络编程&quot;}" data-track-view="{&quot;mod&quot;:&quot;popu_626&quot;,&quot;con&quot;:&quot;python网络编程&quot;}" class="tag-link" href="http://so.csdn.net/so/search/s.do?q=python网络编程&amp;t=blog" target="_blank">python网络编程                        </a><a data-track-click="{&quot;mod&quot;:&quot;popu_626&quot;,&quot;con&quot;:&quot;python套接字&quot;}" data-track-view="{&quot;mod&quot;:&quot;popu_626&quot;,&quot;con&quot;:&quot;python套接字&quot;}" class="tag-link" href="http://so.csdn.net/so/search/s.do?q=python套接字&amp;t=blog" target="_blank">python套接字                        </a><a data-track-click="{&quot;mod&quot;:&quot;popu_626&quot;,&quot;con&quot;:&quot;python聊天实现&quot;}" data-track-view="{&quot;mod&quot;:&quot;popu_626&quot;,&quot;con&quot;:&quot;python聊天实现&quot;}" class="tag-link" href="http://so.csdn.net/so/search/s.do?q=python聊天实现&amp;t=blog" target="_blank">python聊天实现                        </a><a data-track-click="{&quot;mod&quot;:&quot;popu_626&quot;,&quot;con&quot;:&quot;点对点聊天&quot;}" data-track-view="{&quot;mod&quot;:&quot;popu_626&quot;,&quot;con&quot;:&quot;点对点聊天&quot;}" class="tag-link" href="http://so.csdn.net/so/search/s.do?q=点对点聊天&amp;t=blog" target="_blank">点对点聊天                        </a>
    </div>
                    <div class="tags-box">
        <span class="label">个人分类:</span>
                    <a class="tag-link" href="https://blog.csdn.net/lockey23/article/category/6968236" target="_blank">python                       </a><a class="tag-link" href="https://blog.csdn.net/lockey23/article/category/7050514" target="_blank">网络                       </a>
    </div>
                            <div class="tags-box hot-word">
        <span class="label">相关热词:</span>
                    <a class="tag-link" href="https://blog.csdn.net/tzshlyt/article/details/53576822" target="_blank">
        python实现            </a>
                </div>
        </div>

<!-- !empty($pre_next_article[0]) -->
        <div class="related-article related-article-prev text-truncate">
    <a href="https://blog.csdn.net/lockey23/article/details/77921820">
        <span>上一篇</span>python实现的简单点对点(p2p)聊天       </a>
</div>
            <div class="related-article related-article-next text-truncate">
    <a href="https://blog.csdn.net/lockey23/article/details/77951772">
        <span>下一篇</span>nginx安装配置、Nginx支持php        </a>
</div>
</div>

猜你喜欢

转载自blog.csdn.net/zh__quan/article/details/81365811