我正在尝试通过Python中的套接字进行通信。我有一个server.py文件和一个client.py。后者正在请求用户输入并将其发送到服务器。根据用户输入,服务器正在播放2种不同的声音。此操作只能运行一次,但不能再次尝试。
我已经放入了一些print(XYZ)行,以查看程序在哪里停止。发送第一条消息后,不再执行server.py的“ print(” ...“)”行。因此,看起来server_socket.accept()不再成功。为什么会这样?
这是server.py:
SDNA
这是client.py:
import socket
import winsound
fnameBeep = "beep.wav"
fnameBop = "bop.wav"
server_socket = socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
server_addr = ("127.0.0.1", 1337)
server_socket.bind(server_addr)
server_socket.listen(1000)
while True:
print("waiting...")
(client_socket, addr) = server_socket.accept()
print("...")
msg = client_socket.recv(1024)
print(msg)
print("Received: " + str(msg, "utf8"))
if str(msg, "utf8") == '1':
winsound.PlaySound(fnameBeep, winsound.SND_FILENAME)
else:
winsound.PlaySound(fnameBop, winsound.SND_FILENAME)
出了什么问题?常规通信正在运行,但是我想向服务器发送一系列消息。
答案 0 :(得分:1)
你会想要做的第一件事就是将你的accept()
调用上面的while
循环的顶部 - 因为它是你的代码试图接受新的TCP连接在每个命令之后,我认为这不是您想要执行的操作-大概是想保持单个TCP连接打开,并通过该TCP连接接收多个命令。
第二个问题是成帧:关于TCP的要记住的事情是它实现了字节的原始流,并且自己没有对消息进行任何固定的成帧。如果在发送侧执行以下呼叫:
client_socket.send("123")
client_socket.send("456")
client_socket.send("789")
...在接收端,服务器可能会从其后续的recv()调用返回以下数据块:
recv() call #1: 12345
recv() call #2: 67
recv() call #3: 89
...或者,它可能代替(视网络是如何工作的,相月亮等)得到如下:
recv() call #1: 1
recv() call #2: 2345678
recv() call #3: 9
否则它可能会在一次调用中获得所有已发送的数据:
recv() call #1: 123456789
或者它甚至可以通过单独的调用接收每个字节:
recv() call #1: 1
recv() call #2: 2
recv() call #3: 3
recv() call #4: 4
recv() call #5: 5
recv() call #6: 6
recv() call #7: 7
recv() call #8: 8
recv() call #9: 9
...或任何其他组合你能想象的。
所以问题是,考虑到数据分块的不确定性,接收者如何才能知道您的客户端打算发送(“ file_name1.wav”然后是“ file_name2.wav”)而不是仅仅发送(“ file_name1.wavfile_name”) .wav”)或(“文件”,“ name1.wavfile ”,“ name.wav”)等?
为了清楚地解析传入的TCP字节,接收方必须知道如何对其进行成帧。对于像您这样的简单程序,框架逻辑可能很简单-例如只需声明一个规则,即每个字符串的末尾都有换行符。然后,你的服务器可以简单地保持接收字节(并将其添加到字符串的结尾),直到它看到一个换行符字节,此时它知道它已收到完整的用户命令,因此它可以在这一点上处理该命令,然后删除所有字符串(直到并包括换行符),然后继续解析下一个字符串。
另一种方法是让发送方在每个命令之前包含一个短(固定长度)标头,指示接收方在下一个命令中应该看到的字节数。然后服务器可以读取头(因为头是固定长度的,服务器就会知道它需要多少字节读取它具有完整的头前看),然后阅读,多字节,则处理命令,然后重复。