涉及到的知识点
socket创建、多线程、自定义协议的使用。
主要的思路
在服务器端定义client_requserts字典用于存放客户端请求对象,每个客户端上线后都会发送一个消息到服务端注册,以便于后面此字典中的客户端对象做判断来看发送给哪个客户端。
上代码
// server端
#coding:utf8
import socket
import json
from threading import Thread
#申明一个全局客户端字典用于存放客户端请求,相当于客户端到服务端注册,后面可以依靠这个字典实现信息转发
client_requserts = {}
def comm(conn):
#收userid然后添加到client_requsets字典中
userid = conn.recv(1024)
print(f'clinet:{conn}')
print(f'userID:{userid}')
# 每连上来的一个客户端,把userID和请求存放在client_requserts字典中
client_requserts[userid.decode('utf-8')] = conn
print(client_requserts)
while True:
try:
#收客户端发来的数据的头部信息,客户端发来的长度信息是字符串形式,所以要int转换整形数据
headerlen = int(conn.recv(4).decode('utf-8'))
header_data_json = conn.recv(headerlen).decode('utf-8')
header = json.loads(header_data_json)
print(header)
msglen = header.get('msg_len')
localuserid = header.get('localuserID')
peerid = header.get('peerID')
print(f'localuserID:{localuserid},peerid:{peerid},msglen:{msglen}')
#解析完头信息,收主体信息,收recv(msglen)长度的数据
msgdata = conn.recv(msglen)
if msgdata.decode('utf-8') == 'q':
print(f'客户端:{localuserid}退出...')
del client_requserts[localuserid]
print(client_requserts)
break
elif peerid =='a002':#客户端发来的数据携带有对端ip ID号,所以可以以此为发送给谁做判断
print(f'给a002发:{msgdata}')
client_requserts[peerid].send(msgdata)
except Exception as e:
print(e)
break
conn.close()
def run(ip, port):
sk = socket.socket()
sk.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sk.bind((ip, port))
sk.listen(5)
global client_requserts
print(type(client_requserts))
print(f'server:ip({ip})+port({port})已经启动...')
while True:
conn, addr = sk.accept()
#client_requserts['a001'] = conn
print(f'addr:{addr}')
t = Thread(target=comm, args=(conn,))
t.start()
if __name__ == '__main__':
run('127.0.0.1', 9001)
// client1
#coding:utf8
import socket
import time
import json
clientsk=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
clientsk.connect(('127.0.0.1', 9001))
localuserID = 'a001'
peerID = 'a002'
#发送localuserID到服务端注册
clientsk.send(localuserID.encode('utf-8'))
def msg_header(header):
#msg_header函数用于客户端加数据头部
header_json = json.dumps(header)
header_bytes = header_json.encode('utf-8')
header_h = bytes(str(len(header_bytes)),'utf-8').zfill(4)
return (header_bytes,header_h)
def sendmsg(header_h,header_bytes,msg):
#用于发送数据
clientsk.send(header_h)
clientsk.send(header_bytes)
clientsk.send(msg.encode('utf-8'))
while True:
msg = input("请输入:")
if not msg:
print('不能输入为空!')
continue
msg_len = len(msg)
header = {
'localuserID': localuserID,
'peerID': peerID,
'msg_len':msg_len
}
header_bytes,header_h=msg_header(header)
print(header_bytes,header_h)
if msg == 'q':
sendmsg(header_h,header_bytes,msg)
print('已经发q')
time.sleep(1)
break
else:
sendmsg(header_h,header_bytes,msg)
clientsk.close()
// client2
#coding:utf8
import socket
import time
sk=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sk.connect(('127.0.0.1', 9001))
userID='a002'
sk.send(userID.encode('utf-8'))
while True:
data=sk.recv(1024)
print(data.decode('utf-8'))
sk.close()