[英]Socket java can't receive too much data
这是我的套接字实现:
s = new Socket(this.host,this.port);
s.setReceiveBufferSize(2048*2048);
s.setSendBufferSize(2048*2048);
当我收到太多数据时,我的数据会像这样裁剪:
Recieving Message: {"cmd":"209","args":{"type":1,"messages":[{...},{...},{...},{..{...},{�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������...
[编辑]我创建了一个称为InputReader的类,该类实现了Runnable,该类内部具有run方法和while条件:
private class InputReader implements Runnable {
private DarkStarSocketClient main;
private InputStream in;
private boolean disconnected = false;
public InputReader(DarkStarSocketClient main, InputStream in) {
this.main = main;
this.in = in;
}
public void run() {
while (!disconnected) {
try {
byte hi = (byte) in.read();
if (hi == -1) {
main.disconnect();
MessageBuffer dummy = new MessageBuffer(new byte[0]);
postRequest(dummy);
break;
}
byte lo = (byte) in.read();
int len = ((hi & 255) << 8) + (lo & 255) << 0;
byte[] msgBytes = new byte[len];
in.read(msgBytes);
MessageBuffer buf = new MessageBuffer(msgBytes);
handleApplicationMessage(buf);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
这是handleApplicationMessage函数的实现:
private void handleApplicationMessage(MessageBuffer msg) throws Exception {
byte command = msg.getByte();
switch (command) {
case SimpleSgsProtocol.LOGIN_SUCCESS:
reconnectKey = msg.getBytes(msg.limit() - msg.position());
loggedIn = true;
responseHandler.loggedIn();
break;
case SimpleSgsProtocol.LOGIN_FAILURE: {
String reason = msg.getString();
responseHandler.loginFailed(reason);
break;
}
case SimpleSgsProtocol.LOGIN_REDIRECT: {
String host = msg.getString();
int port = msg.getInt();
break;
}
case SimpleSgsProtocol.SESSION_MESSAGE: {
checkLoggedIn();
byte[] msgBytes = msg.getBytes(msg.limit() - msg.position());
responseHandler.receivedSessionMessage(msgBytes);
break;
}
case SimpleSgsProtocol.RECONNECT_SUCCESS:
loggedIn = true;
reconnectKey = msg.getBytes(msg.limit() - msg.position());
responseHandler.reconnected();
break;
case SimpleSgsProtocol.RECONNECT_FAILURE:
String reason = msg.getString();
this.disconnect();
break;
case SimpleSgsProtocol.LOGOUT_SUCCESS:
loggedIn = false;
break;
default:
throw new IOException("Unknown session opcode: " + command);
}
}
您很可能在代码中存在错误。
最常见的错误是在调用read时忽略了实际读取的数据长度。 例如
for(int length; (length = in.read(buffer)) > 0; ) {
// you must use the actual length and not assume the buffer is always full.
如果忽略该长度,则假设只有正确的开始时,整个缓冲区才具有有用的数据。
编辑:正如我猜您正在忽略实际读取的长度。 不管您给它提供多少byte [],最小值都为1。
in.read(msgBytes);
应该
int length = in.read(msgBytes);
// keep reading until you have everything.
如果使用DataOutputStream和DataInputStream,您的生活会简单很多
private final DataInputStream in;
try {
while (!disconnected) {
int length = in.readShort() & 0xFFFF;
byte[] msgBytes = new byte[length];
in.readFully(msgBytes); // keeps reading until the whole buffer is read.
try {
MessageBuffer buf = new MessageBuffer(msgBytes);
handleApplicationMessage(buf);
} catch (Exception ex) {
ex.printStackTrace();
}
}
} catch (EOFException expected) {
} catch (Throwable t) {
System.err.println("Fatal error");
t.printStackTrace();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.