为什么这个客户端-服务器系统不工作(简单)



我试图让一个非常简单的客户端系统变得简单,但我不确定它有什么问题。它应该是一个计算器系统。这是客户端的代码:

import socket
IP = '127.0.0.1'
PORT = 8106
my_socket = socket.socket()
my_socket.connect((IP, PORT))

done = False
while not done:
command = raw_input("choose a command from [ADD, SUB, MUL, DIV, EXIT]")
command = command.upper()
my_socket.send(command)
data = my_socket.recv(20)
new_list = data.split(":")
if command in ["ADD", "SUB", "MUL", "DIV", "EXIT"]:
if command == "ADD":
print new_list[0] + "+" + new_list[1] + "=" + new_list[2]
if command == "SUB":
print new_list[0] + "-" + new_list[1] + "=" + new_list[2]
if command == "MUL":
print new_list[0] + "*" + new_list[1] + "=" + new_list[2]
if command == "DIV":
print new_list[0] + "/" + new_list[1] + "=" + new_list[2]
if command == "EXIT":
done = True
else:
print 'not valid'



这是服务器的代码:

import socket
import random
IP = '0.0.0.0'
PORT = 8106
server_socket = socket.socket()
server_socket.bind((IP, PORT))
server_socket.listen(1)
(client_socket, client_address) = server_socket.accept()

done = False
while not done:
message = client_socket.recv(4)
num1 = random.randint(-101, 100)
print num1
num2 = random.randint(-101, 100)
print num2
if message in ["ADD", "SUB", "MUL", "DIV", "EXIT"]:
if message == "ADD":
result = num1 + num2
elif message == "SUB":
result = num1 - num2
elif message == "MUL":
result = num1 * num2
elif message == "DIV":
result = float(num1) / float(num2)
elif message == "EXIT":
done = True
client_socket.send(str(num1) + ":" + str(num2) + ":" + str(result))
else:
client_socket.send("0:0:0")

现在,当我运行服务器,然后运行客户端,并选择"DIV"几次时,第一次也可以,但在第二次或第三次尝试时,我收到一条错误消息:

print new_list[0] + "/" + new_list[1] + "=" + new_list[2]
IndexError: list index out of range

我不知道为什么会发生这种事。我试图打印"数据"来解决它,有时数据只是一个数字,例如只有46,而不是46:3:15.333

为什么会发生这种情况?

socket.send不能保证对完整数据进行打磨。您的应用程序应该根据socket.send返回值检查发送了多少字节。

或者,只需使用socket.sendall并检查以下异常:

try:
s.sendall(MESSAGE)
except socket.error:
# failed to send

参见文档中的socket.sendsocket.sendall

socket.recv(bufsize[,flags](方法的文档指定以下内容:

一次接收的最大数据量由bufsize指定。

关键部分是bufsize是您可以从单个调用中接收的最大字节数,因此您接收的单个字节字符串在数量和大小上可能与您在另一侧调用send时接收的字节字符串不完全相同。

对于使用默认类型(SOCK_STREAM,即TCP(创建的套接字,唯一能保证的是,您的字节流将以与发送相同的顺序到达。

因此,您必须设计一个协议,允许客户端和服务器识别每个单独消息的边界。

以下是实现这一目标的几种方法:

  1. 在消息本身中包含有关每条消息长度的信息。例如,每条消息的第一个字节可以是一个整数,它给出了消息其余部分的长度,给出了255的最大消息大小(不包括长度前缀(
  2. 使每条消息大小相同。这样,您就不必在消息中对长度进行编码——您只需继续调用recv,直到获得预期的字节数。不过,你必须确保你可以用相同的格式和长度来表达每个数字

Edit:根据kirill的回答,您还必须修复发送数据的代码(例如使用sendall(。不过,如果没有进一步的信息,就不可能说出这些问题中的哪一个导致了你的问题。

最新更新