后续代码更新和功能添加会提交到个人github主页,有兴趣可以一起来完善!
如果只是拿过去运行看结果,请注意平台相关性以及python版本号,本示例开发运行平台为win7x86_64 pycharm community,python版本号为3.5!!!
TALK IS CHEAP, SHOW YOU MY CODE:
客户端
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: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() |
服务端
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
|
#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() |
运行结果示例
服务端(记录着各客户端的操作):
客户端1:
有注册、建群、群聊、点对点聊天
客户端2:
客户端3:
要拷贝代码运行的话请注意平台(win7.x86_64)和python版本号(python3.5)!!!
原文链接:http://blog.csdn.net/Lockey23/article/details/77940518