打印时套接字的接收端会拆分数据 - java

因此,在使用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("abcdef")完全相同。在套接字的另一端,当您去接收时,它可能会在第一个发送到达并给您"abc"后立即返回,但它也很容易返回"abcdef""a"或。它们都是完全合法的,并且您的代码必须能够处理所有这些。

如果要单独处理整个消息,则需要构建一个描述消息的协议-是否意味着使用一些不能出现在实际数据中的分隔符(可能是因为,如果确实出现在实际数据中,则可能是因为转义),或为每条消息加上前缀,或使用一些自描述格式(如JSON)。

看来您正在构建这种东西,因为您出于某种原因获得了"abcd"。但是,您仍然需要添加其余部分-围绕接收字节循环,将它们添加到缓冲区中,将所有完整的消息从缓冲区中分离出来进行处理,并在下一个循环的最后保留所有不完整的消息。当然,在另一侧发送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分隔每条消息中的字段,而不是分隔消息。如果是这样,只需选择一个永远不会出现在您的数据中的字符,并使用它代替上面的|(然后在|内部执行msg.split('|'))。一个非常好的选择是process_message,因为然后(在Python方面)您可以使用\n,它为您提供了一个类似文件的对象,该对象可以为您进行缓冲,并且在迭代时逐行生成(或根据需要致电socket.makefile)。

有关更多信息,请参见Sockets are byte streams, not message streams。

附带说明一下,我还删除了readline标志,因为只有一次要设置它时,您还要去running,所以它没有任何用处。 (但是,如果要测试标志,请使用break,而不是while running:。)

Java-搜索字符串数组中的字符串 - java

在Java中,我们是否有任何方法可以发现特定字符串是字符串数组的一部分。我可以避免出现一个循环。例如String [] array = {"AA","BB","CC" }; string x = "BB" 我想要一个if (some condition to tell wheth…

Java-如何将此字符串转换为日期? - java

我从服务器收到此消息,我不明白T和Z的含义,2012-08-24T09:59:59Z将此字符串转换为Date对象的正确SimpleDateFormat模式是什么? java大神给出的解决方案 这是ISO 8601标准。您可以使用SimpleDateFormat simpleFormat = new SimpleDateFormat("yyyy-MM…

Java RegEx中的单词边界\ b - java

我在使用\b作为Java Regex中的单词定界符时遇到困难。对于text = "/* sql statement */ INSERT INTO someTable"; Pattern.compile("(?i)\binsert\b");找不到匹配项Pattern insPtrn = Pattern.compile(&…

Java Double与BigDecimal - java

我正在查看一些使用双精度变量来存储(360-359.9998779296875)结果为0.0001220703125的代码。 double变量将其存储为-1.220703125E-4。当我使用BigDecimal时,其存储为0.0001220703125。为什么将它双重存储为-1.220703125E-4? 参考方案 我不会在这里提及精度问题,而只会提及数字…

Java:线程池如何将线程映射到可运行对象 - java

试图绕过Java并发问题,并且很难理解线程池,线程以及它们正在执行的可运行“任务”之间的关系。如果我创建一个有10个线程的线程池,那么我是否必须将相同的任务传递给池中的每个线程,或者池化的线程实际上只是与任务无关的“工人无人机”可用于执行任何任务?无论哪种方式,Executor / ExecutorService如何将正确的任务分配给正确的线程? 参考方案 …