TCP通讯使用定长报文。
格式:
请求 :6byte(表示后续报文长度len)+ byte[len]
响应: 6byte(表示后续报文长度len)+ byte[len]
从响应inputstream里按长度头里收到的len继续接收数据,发现有接收不全的情况。
通讯程序大概这样:
Socket socket = null;
InputStream inputStream = null;
OutputStream outputStream = null;
byte[] data = {};//要发送的数据
try {
//创建Socket对象
socket=new Socket(host,port);
//根据输入输出流和服务端连接
outputStream=socket.getOutputStream();//获取一个输出流,向服务端发送信息
//补充长度头为6位字符串
String lenString = PadLen(data.length,6);
//发送长度头
outputStream.write(lenString.getBytes());
//发送数据
outputStream.write(data);
outputStream.flush();
socket.shutdownOutput();//关闭输出流
//获取一个输入流,接收服务端的信息
inputStream=socket.getInputStream();
//接收长度头
byte[] len = new byte[6];
inputStream.read(len);
//按长度头数据接收实际数据
int bodylen = Integer.parseInt(new String(len));
byte[] reqData = new byte[bodylen];
/**
!!!就是这一步有问题,根据头指定长度继续接收,发现接收不全!!!
*/
int readLen =inputStream.read(reqData);
//关闭相对应的资源
inputStream.close();
outputStream.close();
socket.close();
} catch (Exception e) {
logger.error("通讯异常",e);
}
就是按响应长度头接收实际数据时,一般数据长度每问题,当实际长度比较大,超过1万字节,实际在按长度接收,接收到长度只有6000多字节。不知为什么。百度说有TCP分包发送啥的也不懂。
最后解决方法,直接使用common-io包里的工具方法,处理流。不按长度接收了。
byte[] recvData = IOUtils.toByteArray(inputStream);
IOUtils.toByteArray方法的处理方式大致这样(2.6版本源码)
InputStream input;
//新建一个输出流
ByteArrayOutputStream output = new ByteArrayOutputStream();
/**
* copy(input, output);
将input输入流中数据复制到构造的输出流中
*/
long count = 0;
int n;
byte[] buffer = new byte[4096];
//循环读取到buffer
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
}
//转换成byte array
return output.toByteArray();