我正在使用Commons-IO从Socket读取和写入。事情一直有效,直到有效载荷大小为1448/2896最大
以下是代码段。真的不确定如何处理它。 检查系统缓冲区大小
$ cat /proc/sys/net/ipv4/tcp_wmem
4096 16384 4194304
public static void usingCommonsIO(){
Socket socket = null;
try {
socket = new Socket(serverIP, 55000);
IOUtils.write(request.getBytes(), socket.getOutputStream());
System.out.println("Message Sent....");
StringBuilder response = new StringBuilder();
String resp =IOUtils.toString(socket.getInputStream(), "UTF-8");
System.out.println(resp);
} catch (IOException e) {
e.printStackTrace();
}
}
或者尝试使用DataInputStream但没有运气。代码剪辑如下。
public static void usingDataIOStream(String requestStr){
Socket socket = null;
try {
socket = new Socket("192.168.1.6", 55000);
System.out.println("Request Length -:" + request.length());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.write(requestStr.getBytes("UTF-8"), 0, requestStr.length());
out.flush();
System.out.println("Message Sent....");
DataInputStream din = new DataInputStream(socket.getInputStream());
byte[] response = new byte[16*1024];
int responseLength = din.read(response);
System.out.println("Response -:" + new java.lang.String(response, 0, responseLength));
} catch (IOException e) {
e.printStackTrace();
}
}
令人困惑的部分是,相同的代码有时仅使用1448字节,有时最多只能处理2896字节。没有具体的模式。
更新1
要模拟它,尝试自己编写Server套接字,代码如下。注意到这一点的奇怪之处是,在第一次请求时,读取并正确接收了大小为6500的有效载荷。连接重置从第二个请求开始。我在这里错过了什么吗?
public static void usingBAOS() throws IOException {
server = new ServerSocket(port);
Socket socket = null;
DataInputStream din = null;
DataOutputStream dos = null;
while (true) {
System.out.println("Waiting for Client...");
try {
// Accepting Client's connection
socket = server.accept();
System.out.println("Connnected to client " + socket.getInetAddress());
din = new DataInputStream(socket.getInputStream());
// Read request payload from Socket
String requestString = readRequest(din);
System.out.println("Request Read.....");
System.out.println("Writing Response.....");
// Writing response to socket
dos = writeResponse(socket, requestString);
} catch (IOException e) {
e.printStackTrace();
}finally {
//close resources
din.close();
System.out.println("InputStream is closed......");
dos.close();
System.out.println("OutputStream is closed......");
socket.close();
System.out.println("Socket is closed......");
}
}
}
private static DataOutputStream writeResponse(Socket socket, String requestString) throws IOException {
String responseString = "Hi Client" + requestString;
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
//write object to Socket
dos.write(responseString.getBytes(),0, responseString.getBytes().length);
dos.flush();
return dos;
}
private static String readRequest(DataInputStream din) throws IOException {
byte[] response = new byte[16*1024];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int n = 0;
boolean read = true;
while(read){
n = din.read(response);
baos.write(response, 0, n);
if(baos.toString().length() == n){
read = false;
}
}
baos.flush();
String requestString = baos.toString();
return requestString;
}
答案 0 :(得分:0)
尽管在编写此答案时这个问题已经过时,但我还是将其放在此处,以备其他人解决。在Android 8.0设备上使用缓冲的数据输入和输出流时,我天真地认为这样做会遇到相同的问题:
int len = 2304;
byte[] data = new byte[len];
inputStream.read(data, 0, len);
将读取我通过套接字发送的所有数据。但是,正如@Kayaman在评论中所建议的那样,即使有可用的字节,也不能保证实际上从缓冲区读取了len
个字节的数据。实际上,它在documentation中:
public final int read(byte[] b, int off, int len) throws IOException
从包含的输入流中读取多达
len
个字节的数据到一个字节数组中。尝试读取多达len个字节,但可能读取的字节数较小,可能为零。实际读取的字节数以整数形式返回。
实际上,如果它不能读取所有数据,那么唯一的判断方法就是捕获返回的值。然后,我的解决方案是监视实际从流中读取的字节数,并在循环中仅调用read()
,如下所示:
int i = 0;
len = 2304;
byte[] data = new byte[len];
while (i < len)
{
i += socket.inputStream.read(data, i, len - i);
}
希望这对某人有帮助。