python实现简单聊天应用(群聊和点对点均实现)
后续代码更新和功能添加会提交到个人github主页,有兴趣可以一起来完善!
如果只是拿过去运行看结果,请注意平台相关性以及python版本号,本示例开发运行平台为win7x86_64 pycharm community,python版本号为3.5!!!
TALK IS CHEAP, SHOW YOU MY CODE:
客户端
#coding:utf-8'''file:client.py.pydate:2017/9/11 11:01author:lockeyemail:[email protected]:win7.x86_64 pycharm python3desc:p2p communication clientside'''from socket import *import threading,sys,json,re#引入json模块主要是为了数据的封装传输,re的话是做一些合法性的验证HOST = '192.168.1.7'PORT=8022BUFSIZE = 1024 ##缓冲区大小 1KADDR = (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 Falsedef 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 Falsedef addGroup():#群组添加 groupname = input('Please input group name: ') if not re.findall(myre, groupname): print('group name illegal!') return None return groupnamedef 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.pydate:2017/9/11 14:43author:lockeyemail:[email protected]:win7.x86_64 pycharm python3desc:p2p communication serverside'''import socketserver,json,timeimport subprocessconnLst = []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 = conObjclass 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')) continueif __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)!!!
再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.****.net/jiangjunshow
后续代码更新和功能添加会提交到个人github主页,有兴趣可以一起来完善!
如果只是拿过去运行看结果,请注意平台相关性以及python版本号,本示例开发运行平台为win7x86_64 pycharm community,python版本号为3.5!!!
TALK IS CHEAP, SHOW YOU MY CODE:
客户端
#coding:utf-8'''file:client.py.pydate:2017/9/11 11:01author:lockeyemail:[email protected]:win7.x86_64 pycharm python3desc:p2p communication clientside'''from socket import *import threading,sys,json,re#引入json模块主要是为了数据的封装传输,re的话是做一些合法性的验证HOST = '192.168.1.7'PORT=8022BUFSIZE = 1024 ##缓冲区大小 1KADDR = (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 Falsedef 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 Falsedef addGroup():#群组添加 groupname = input('Please input group name: ') if not re.findall(myre, groupname): print('group name illegal!') return None return groupnamedef 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.pydate:2017/9/11 14:43author:lockeyemail:[email protected]:win7.x86_64 pycharm python3desc:p2p communication serverside'''import socketserver,json,timeimport subprocessconnLst = []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 = conObjclass 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')) continueif __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)!!!