[英]Receiving end of socket splits data when printed
因此,在使用Java和Python编程套接字时,我偶然发现了一些奇怪的东西。
当使用Java将消息发送到Python套接字的接收端时,即使不希望这样做,也会将消息分为两部分。
我可能在导致此问题的某个地方犯了一个错误,但我真的不知道这是什么。
您可以看到Java在一个命令中发送了“ Test1”,而Python仅收到了该消息的一部分:
http://i.imgur.com/tbwa7C5.png
Pyhton服务器套接字源:
'''
Created on 23 okt. 2014
@author: Rano
'''
#import serial
import socket
HOST = ''
PORT = 1234
running = True;
skt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
skt.bind((HOST, PORT))
skt.listen(1)
conne, addr = skt.accept()
#ser = serial.Serial('/dev/tty.usbmodem411', 9600)
while running == True:
data = conne.recvall(1024)
if(data == "quit"):
running = False
break
rawrecvstring = data + ""
recvstring = rawrecvstring.split("|")
print(recvstring[0])
#_______________________ABOVE IS RECEIVE_______________UNDER IS SEND_______________________#
# sendstring = ser.readline()
# if sendstring != "":
# conne.sendall(sendstring)
conne.close()
#ser.close()
和Java Socket发送功能:
private String message;
private DataOutputStream out;
private BufferedReader in;
private Socket socket;
private boolean socketOnline;
public SocketModule(String IP, int Port){
try {
socket = new Socket(IP, Port);
out = new DataOutputStream(socket.getOutputStream());
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
};
void setMessage(String s){
try {
out.writeBytes(s);
out.flush();
System.out.println("message '" + s + "' sent!\n");
} catch (IOException e) {
e.printStackTrace();
}
};
关于为何拆分消息有任何想法吗?
TCP是流协议,不是消息协议。
就TCP而言, s.send("abd"); s.send("def");
s.send("abd"); s.send("def");
与s.send("abcdef")
完全相同。 在套接字的另一端,当您去接收时,它可能会在第一个发送到达时立即返回并给您"abc"
,但它也可以很容易地返回"abcdef"
或"a"
或"abcd"
。 它们都是完全合法的,并且您的代码必须能够处理所有这些。
如果要单独处理整个消息,则需要构建一个描述消息的协议-是否意味着使用一些不能出现在实际数据中的分隔符(可能是因为,如果确实出现在实际数据中,则可能是因为转义),或为每条消息加上前缀,或使用一些自描述格式(如JSON)。
看来您正在构建这种东西,因为您出于某种原因而获得了split('|')
。 但是,您仍然需要添加其余部分-围绕接收字节循环,将它们添加到缓冲区中,将所有完整的消息从缓冲区中分离出来进行处理,并在下一个循环的最后保留所有不完整的消息。 并且,当然,发送|
另一侧的分隔符。
例如,您的Java代码可以执行以下操作:
out.writeBytes(s + "|");
然后,在Python端:
buf = ""
while True:
data = conne.recvall(1024)
if not data:
# socket closed
if buf:
# but we still had a leftover message
process_message(buf)
break
buf += data
pieces = buf.split("|")
buf = pieces.pop()
for piece in pieces:
process_message(piece)
该process_message
函数可以处理特殊的“退出”消息,打印出任何您想要的内容。 (如果足够简单,则可以将其内联到被称为的两个位置。)
从评论看来,您想使用它|
分隔每个消息中的字段,而不分隔消息。 如果是这样,只需选择一个永远不会出现在您的数据中的字符并用它代替|
上面(然后在process_message
内执行msg.split('|')
)。 一个非常好的选择是\\n
,因为然后(在Python端),您可以使用socket.makefile
,它为您提供了一个类似文件的对象,该对象可以为您进行缓冲,并且在迭代时socket.makefile
生成(或如果愿意,请致电readline
)。
有关更多信息,请参见套接字是字节流,而不是消息流 。
附带说明一下,我也删除了running
标志,因为只有在您要设置它时,您才会break
,所以它没有任何用处。 (但是,如果你要测试一个标志,只要使用while running:
不是while running == True:
。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.