后续代码更新和功能添加会提交到个人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