[英]Send dictionary in python socket
我想通過 python 套接字發送字典。
我嘗試對發送數據進行編碼,然后在接收點進行編碼
但是無法轉換的接收數據存在問題並且無法轉換為字典。
這是我的代碼:
client.py
客戶端.py :
HEADER_LENGTH = 512
IP = "127.0.0.1"
PORT = 963
my_username = input("Username: ")
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((IP, PORT))
client_socket.setblocking(False)
username = my_username.encode('utf-8')
username_header = f"{len(username):<{HEADER_LENGTH}}".encode('utf-8')
client_socket.send(username_header + username)
while True:
message = input(f"{my_username} > ")
if message:
message = message.encode('utf-8')
message_header = f"{len(message)}:<{HEADER_LENGTH}".encode('utf-8')
# {'header': {message_header}, 'data': {message}}
send_dict = {} # 'header': message_header, 'data': message
send_dict["header"] = str(message_header)
send_dict["data"] = str(message)
client_socket.send(json.dumps(send_dict).encode('utf-8')) # message_header + message
try:
while True:
# Receive ...
username_header = client_socket.recv(HEADER_LENGTH)
if not len(username_header):
print("Connection closed by the server")
sys.exit()
username_length = int(username_header.decode('utf-8').strip())
username = client_socket.recv(username_length).decode(('utf-8'))
message_header = client_socket.recv(HEADER_LENGTH)
message_length = int(message_header.decode('utf-8').strip())
message = client_socket.recv(message_length).decode(('utf-8'))
print(f"{username} > {message}")
except IOError as e:
if e.errno != errno.EAGAIN and e.errno != errno.EWOULDBLOCK:
print('Reading error', str(e))
sys.exit()
continue
except Exception as e:
print('General error', str(e))
sys.exit()
Class server.py
:
HEADER_LENGTH = 512
IP = "127.0.0.1"
PORT = 963
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((IP, PORT))
server_socket.listen()
socket_list = [server_socket]
clients = {}
def receive_message(client_socket):
# print(f"client socket: {client_socket}")
# try:
message_header = client_socket.recv(HEADER_LENGTH)
if not len(message_header):
print("return from receive message /condition/")
return False
print(f"message header: {type(message_header)}")
print(f"message header: {message_header}")
print(f"message header decode : {type(message_header.decode('utf-8').strip())}")
message_header_dict = message_header.decode('utf-8').strip()
# print(f"message header replaced : {message_header}")
print(f"message header replaced : {type(message_header_dict)}")
print(f"message header replaced : {message_header_dict}")
# print("message header header : " + message_header_dict['header'].decode('utf-8').strip())
json_message_header = json.loads(message_header_dict)
print(f"message header replaced : {json_message_header}")
print(f"message header replaced : {json_message_header['data']}") # Error line
message_length = int(message_header.decode("utf-8").strip())
return {"header": message_header, "data": client_socket.recv(message_length)}
# except:
# print("return from receive message /except/")
# return False
while True:
read_sockets, _, exception_sockets = select.select(socket_list, [], socket_list)
for notified_socket in read_sockets:
if notified_socket == server_socket:
client_socket, client_address = server_socket.accept()
user = receive_message(client_socket)
if user == False:
continue
socket_list.append(client_socket)
clients[client_socket] = user
print(
f"Accept new connection from {client_address[0]}:{client_address[1]} username:{user['data'].decode('utf-8')}")
else:
message = receive_message(notified_socket)
if message == False:
print(f"close connection from: {clients[notified_socket]['data'].decode('utf-8')}")
socket_list.remove(notified_socket)
del clients[notified_socket]
continue
user = clients[notified_socket]
print(f"Received message from: {user['data'].decode('utf-8')}: {message['data'].decode('utf-8')}")
for client_socket in clients:
if client_socket != notified_socket:
client_socket.send(user['header'] + user['data'] + message['header'] + message['data'])
for notified_socket in exception_sockets:
socket_list.remove(notified_socket)
del clients[notified_socket]
您的客戶發送 JSON。 然后,您的服務器讀取整個 JSON 消息並嘗試將其解釋為 integer。 繁榮。
您基本上有 3 個選項來傳輸完整消息: 發送字節並假設您收到了整個消息,而不再從單次讀取中接收(最不可靠); 使用分隔符(例如,CRLF)並確保它不出現在消息中(受限數據流); 或發送一個字節數,后跟消息字節(長度+數據,最可靠)。 看起來你已經混合了第一種和第三種方法,這基本上是行不通的。
要使用長度+數據將 dict 序列化為 JSON 進行傳輸,首先對 dict 進行 JSON 編碼,然后對結果字符串進行 UTF8 編碼以獲取消息字節。 從這一點開始,直到服務器反序列化消息,代碼都在使用字節。
要發送長度+數據, struct
模塊是您的朋友。 定義打包/解包說明符(基本上,選定大小的 integer 加上字節串)。 例如, "!Hs"
將支持高達 64K 的消息字節串。
在客戶端...
struct.pack
創建二進制消息 (<length-header><message-bytes>)。socket.sendall
發送二進制消息(發送消息可能需要多次send
調用,而sendall
會為您處理)。在服務器...
socket.recv
僅接收 header 字節(例如,4 或 8 字節)。struct.unpack
解壓字節數。socket.recv
僅接收消息字節(即byte_count字節)您可以使用 pickle 或其更快的版本 cPickle 來序列化數據和反序列化數據。
import pickle
# for serializing data
pickle.dumps(data_to_serialized)
# for deserializing
pickle.loads(data_to_be_deserialized)
下面是示例 function 用於使用 pickle 進行序列化發送和接收數據:
def send_data(conn, data):
serialized_data = pickle.dumps(data)
conn.sendall(struct.pack('>I', len(serialized_data)))
conn.sendall(serialized_data)
def receive_data(conn):
data_size = struct.unpack('>I', conn.recv(4))[0]
received_payload = b""
reamining_payload_size = data_size
while reamining_payload_size != 0:
received_payload += conn.recv(reamining_payload_size)
reamining_payload_size = data_size - len(received_payload)
data = pickle.loads(received_payload)
return data
您可以在https://github.com/vijendra1125/Python-Socket-Programming.git找到示例程序
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.