因为实际需求,代码中只传输了整数数据。稍作修改即可传输其他类型数据
数据收发逻辑
建立连接之后,如果发送了不属于已有cid
(字典key)的8bit char
数据,则为其在1~127
分配一个新的cid
。如果是已有cid
,则继续读取一个8bit char
作为命令。w
为更新cid
对应值,l
为列出所有cid
,r
为读取一个cid
对应的值。
- 对于
w
,传输一个32bit int
值即可对相应cid
进行更新。特别地,传输0
将会删除该cid
。 - 对于
l
,服务器将首先发回一个8bit char
代表cid
的个数,紧接着依次发送每个cid
,即字典的key,每个值均为8bit
。 - 对于
r
,接收一个8bit char
的cid
,返回该cid
对应的32bit int
值。
错误处理
- 返回
-1
:接收数据错误,该cid
对应的值将被更新为-1
- 返回
-2
:初始字典值 - 返回
-3
:获取cid
错误 - 返回
-4
:获取cmd
错误 - 返回
-5
:目标cid
错误,字典中无该key
对应值 - 返回
-6
:客户端(cid
)数已满
代码实现
服务端
#!/usr/bin/python3
#server
import socket # 导入 socket 模块
import random
def sendnbyte(c, data, num):
try:
c.send(data.to_bytes(num, "little"))
print("发出数据:", data, "字节数为", num)
except Exception as e:
print("发送数据错误!\n", e)
def getint(c):
try:
return int.from_bytes(c.recv(4), byteorder = "little")
except Exception as e:
print("接收数据错误!\n", e)
return -1 & 0xffffffff
def getcid(c):
try:
return int.from_bytes(c.recv(1), byteorder = "little")
except Exception as e:
print("获取cid错误!\n", e)
return -3 & 0xffffffff
def getcmd(c):
try:
return c.recv(1).decode()
except Exception as e:
print("获取char错误!\n", e)
return -4 & 0xffffffff
s = socket.socket() # 创建 socket 对象
host = "0.0.0.0" # 获取本地ip
port = 12345 # 设置端口
s.bind((host, port)) # 绑定端口
s.listen(127) # 等待客户端连接
data = {} # 客户端数据字典
while True:
c,addr = s.accept() # 建立客户端连接
print("连接地址", addr)
cid = getcid(c)
if cid in data:
print("客户端id是", cid)
cmd = getcmd(c)
print("得到命令:", cmd)
if(cmd == 'w'): #w 119
data[cid] = getint(c)
print("写入数据:", data[cid], '@', cid)
if data[cid] == 0:
data.pop(cid)
print("删除cid:", cid)
elif(cmd == 'l'): #l 108
print("现有cid:", data.keys())
sendnbyte(c, len(data), 1)
for key in data.keys(): sendnbyte(c, key, 1)
elif(cmd == 'r'): #r 114
cid = getcid(c)
if cid in data:
print('获取', cid, "的值并", end = '', sep = '')
sendnbyte(c, data[cid], 4)
else:
print("目标cid错误!")
sendnbyte(c, -5 & 0xffffffff, 4)
else:
if(len(data) >= 127):
print("客户端数已满!")
sendnbyte(c, -6 & 0xffffffff, 1)
continue
cid = random.randint(1, 127)
while cid in data: cid = random.randint(1, 127)
print("为新客户端分配id:", end = '')
sendnbyte(c, cid, 1)
data[cid] = -2 & 0xffffffff
c.close() # 关闭连接
客户端
#client
import socket # 导入 socket 模块
s = socket.socket() # 创建 socket 对象
host = socket.gethostbyname("localhost") # 获取服务器ip
port = 12345 # 设置端口号
data = 10086 # 欲传送数据
rdata = 0 # 接收数据变量
print("连接到服务器: ", host, ':', port, sep = '')
s.connect((host, port))
cid = 0
s.send(cid.to_bytes(1, "little"))
cid = int.from_bytes(s.recv(1), byteorder = "little")
print("获得id:", cid)
s.close()
s = socket.socket()
s.connect((host, port))
s.send(cid.to_bytes(1, "little"))
s.send('w'.encode())
data = int(input("请输入欲传输整数数据: "))
s.send(data.to_bytes(4, "little"))
print("传输数据:", data, "对应cid:", cid)
s.close()
s = socket.socket()
s.connect((host, port))
s.send(cid.to_bytes(1, "little")) # 本机cid
s.send('l'.encode())
leng = int.from_bytes(s.recv(1), byteorder = "little")
cidlist = []
while leng:
cidlist.append(int.from_bytes(s.recv(1), byteorder = "little"))
leng = leng - 1
cidlist.sort()
print("现有cid:", cidlist)
s.close()
s = socket.socket()
s.connect((host, port))
s.send(cid.to_bytes(1, "little")) # 本机cid
s.send('r'.encode())
cid = int(input("请输入欲链接cid: "))
while cid not in cidlist:
cid = int(input("输入id不在列表中!\n请输入欲链接cid: "))
s.send(cid.to_bytes(1, "little")) # 欲链接cid
rdata = int.from_bytes(s.recv(4), byteorder = "little")
print("接受数据:", rdata, "对应cid:", cid)
s.close()