我正在尝试使用Java将套接字发送到服务器:
_socket = new Socket(host, port);
_writer = new DataOutputStream(_socket.getOutputStream());
public void send(String data){
_writer.writeBytes( data );
_writer.flush();
}
我想将数据作为同一个数据包发送,有时它会分成多个数据包。我不知道它是否足够清楚,我缺少一些词汇。
如果我发送:
“0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ”
服务器可能会将数据接收到3个数据包中:
"0123456"
"789abcdefghijklmno"
"pqrstuvwxyz"
有没有办法不将您发送的数据分成多个数据包?
BufferedOutputStream
似乎解决了这个问题。
答案 0 :(得分:2)
BufferedOutputStream
似乎解决了这个问题。
答案 1 :(得分:0)
我必须承认我不知道Sockets
分割数据,但我想这是可以预期的。您可以选择的一个选项就是使用一个字符或一组字符来表示传输的结束。即:
String data = "Hello there, this is a long packet";
String delimiter = "ENDOFPACKET"; // Obviously, it will need to be more complex.
String packet = data + delimiter;
send(packet);
在您的阅读器中,不是处理每个数据包,只需连接到字符串,直到找到delimiter
值。
答案 2 :(得分:0)
也许设置缓冲区大小会有所帮助:
http://docs.oracle.com/javase/6/docs/api/java/net/Socket.html#setSendBufferSize%28int%29
但我没有尝试过这个选项。我必须承认,我希望缓冲区不仅仅是十几个字节,就像你的情况一样。
答案 3 :(得分:0)
我做了一些测试,在我的情况下它完美无缺。我只在一次阅读中收到了整个数据。
我使用这个功能:
public void send(String data)
{
try
{
socket.getOutputStream().write(data.getBytes());
}
catch (Exception e)
{
}
}
我认为即使您使用3次读取来获取数据,也不一定意味着您收到3个数据包,可能是1,2或甚至超过3.在不知道服务器如何读取的情况下很难正确回答问题数据。例如,如果我在队列中有200个字节,并且我在50字节缓冲区中读取,那么我需要4次读取来获取数据。这很明显,但值得一提。
答案 4 :(得分:0)
这是流协议的基本功能,例如TCP / IP或本地套接字:它是一个保证以正确顺序传递的字节流,它是没有数据包边界的。
因此,您需要自己的协议来分离数据包。有两种基本方法。
首先,您可以拥有一个特殊的字节或字节序列,例如文本流中的简单换行符或字节0,它标记了消息的结束。
其次,你可以有一个包头,它可以像32位原始二进制数一样简单,通常按网络字节顺序,告诉消息的大小,然后是实际消息数据的那么多字节。这适用于二进制数据。
或者使用混合方法:首先读取一行文本标题,结束于下一个换行符,您将其解析为文本数据,其中包括长度。然后读取那么多字节的原始二进制数据,然后读取下一个标题行作为文本,依此类推。当您可以直观地看到您的服务器和客户端是否保持同步时,这也更容易调试,并且它也很容易扩展,因为标头的大小不固定。