我有一個小的服務器客戶端分配在Python 2.7中的問題。「結構。錯誤:解壓縮時需要一個長度爲4」的字符串參數時切片[:3]
客戶端可以發送5種類型的請求到服務器:
- 獲取服務器的IP
- 獲得服務器
- 運行CMD在服務器上的命令上的目錄的內容,並獲取輸出
- 打開計算器服務器
- 斷開
這是錯誤我得到:
error:
msg_type, data_len = unpack("BH", client_structs[:3])
struct.error: unpack requires a string argument of length 4
代碼:
client_structs = client_soc.recv(1024)
msg_type, data_len = unpack("BH", client_structs[:3])
不子串包含4個字符,包括空?
希望能解釋這個錯誤+如何解決它。
整個服務器代碼:
__author__ = 'eyal'
from struct import pack, unpack, calcsize
import socket
from os import listdir
from subprocess import check_output, call
def server():
ser_soc = socket.socket()
ser_soc.bind(("0.0.0.0", 8080))
ser_soc.listen(1)
while True:
accept_flag = raw_input("Would you like to wait for a client? (y/n) ")
if accept_flag == "y":
client_soc, client_address = ser_soc.accept()
while True:
client_structs = client_soc.recv(1024)
data_size = calcsize(client_structs) - 3
data_str = 'c' * data_size
unpacked_data = unpack("BH" + data_str, client_structs)
if unpacked_data[0] == 1:
ip = socket.gethostbyname(socket.gethostname())
ip_data = 'c' * len(ip)
to_send = pack("BH" + str(len(ip)) + ip_data, unpacked_data[0], len(ip), ip)
elif unpacked_data[0] == 2:
content = listdir(str(unpacked_data[2]))
content_str = "\r\n".join(content)
content_data = 'c' * len(content_str)
to_send = pack("BH" + str(len(content_str)) + content_data, unpacked_data[0],
len(content_str), content_str)
elif unpacked_data[0] == 3:
command = str(unpacked_data[2:]).split()
output = check_output(command)
message_data = 'c' * len(output)
to_send = pack("BH" + message_data, unpacked_data[0], len(output), output)
elif unpacked_data[0] == 4:
call("gnome-calculator")
msg_data = 'c' * len("The calculator is open.")
to_send = pack("BH" + msg_data, unpacked_data[0], len("The calculator is open."),
"The calculator is open.")
elif unpacked_data[0] == 5:
client_soc.close()
break
else:
to_send = pack("BH" + 'c' * len("invalid message type, try again"),
unpacked_data[0], len("invalid message type, try again"),
"invalid message type, try again")
if unpacked_data[0] != 5:
client_soc.send(to_send)
else:
break
ser_soc.close()
def main():
server()
if __name__ == "__main__":
main()
整個客戶端代碼:
__author__ = 'eyal'
from struct import pack, unpack, calcsize
import socket
def client():
my_soc = socket.socket()
my_soc.connect(("127.0.0.1", 8080))
while True:
send_flag = raw_input("Would you like to send the server a request? (y/n) ")
if send_flag == "y":
msg_code = input("What type of request would you like to send?\n"
"1. Get the server's IP address.\n"
"2. Get content of a directory on the server.\n"
"3. Run a terminal command on the server and get the output.\n"
"4. Open a calculator on the server.\n"
"5. Disconnect from the server.\n"
"Your choice: ")
if msg_code == 1 or msg_code == 4 or msg_code == 5:
to_send = pack("BH", msg_code, 0)
elif msg_code == 2:
path = raw_input("Enter path of wanted directory to get content of: ")
to_send = pack("BH" + 'c' * len(path), msg_code, len(path), path)
elif msg_code == 3:
command = raw_input("Enter the wanted terminal command, including arguments: ")
to_send = pack("BH" + 'c' * len(command), msg_code, len(command), command)
else:
print "Invalid message code, try again\n"
if 1 <= msg_code <= 5:
my_soc.send(to_send)
else:
break
data = my_soc.recv(1024)
unpacked_data = unpack("BH" + 'c' * (calcsize(data) - 3), data)
print "The server's response to your type-" + str(msg_code) + " request:"
print unpacked_data[2]
my_soc.close()
def main():
client()
if __name__ == "__main__":
main()
如果您使用Python 2.7或更高版本,請使用'unpack_from',並且您可以簡單地傳遞整個字符串; 'unpack_from'將使用它需要的字節並忽略其餘部分。 – chepner
同時,就像我在[您的上一個問題](http://stackoverflow.com/questions/29996458/struct-error-bad-char-in-struct-format)中所述,停止發佈整個代碼的轉儲。創建一個顯示相關部分的[MCVE](http://stackoverflow.com/help/mcve),並解釋實際應該做什麼以及它的做法有什麼不同,而不是讓我們讀取所有代碼並猜測它應該和它實際做的有什麼不同。 – abarnert