定制socket传输协议。增加包头、命令、数据长度、数据体、结束位。比如发送消息:,
String msg = "你好"
byte[] byBuffer = msg.getBytes()
//加入定制的协议该条数据位:
byte[] b = new byte[4+byBuffer.length]
b[0] = 0xFFFFF//随便定义,包头
b[1] = 0x01//命令
b[2] = byBuffer.length//数据长度
b[3 - n] = byBuffer//数据
b[b.length -1] = 0x0d//结束
接收方接收到该数据后判断包头是否一致,不一致则不要,根据b[2]数据长度来去数据,第一次未接收完继续接收第二次,直到接收数据长度==b[2]为止。一条完整的数据就出来了。
写得很随意,理解理解~
try{
InputStream is = socket.getInputStream()
while(running)
{
/*
* 读取消息长度
*/
byte[] totalLen = new byte[4]
int readLen = 0//本次读取的字节数
int position = 0//已经读取数据的下一个位置
while((readLen=is.read(totalLen,position,(4-position)))>=0)
{
position = position + readLen
if(position==4)
{
break
}
}
if(readLen<0)
{//读取到EOF,socket已close或reset
throw new SocketException("读取数据流结尾.")
}
int length = SGIP.byteArrayToInt(totalLen)
ByteBuffer mesg = ByteBuffer.allocate(length)
mesg.order(SGIP.getByteOrder())
mesg.put(totalLen)
//读取所有消息
readLen = 0
position = mesg.position()
while((readLen=is.read(mesg.array(), position, mesg.remaining()))>=0)
{
position = position + readLen
mesg.position(position)
if(mesg.remaining()==0)
{
break
}
}
if(readLen<0)
{//读取到EOF,socket已close或reset
throw new SocketException("读取数据流结尾.")
}
mesg.position(0)
//解析消息
mesg.order(ByteOrder.BIG_ENDIAN)
try
{
//解析mesg
}
catch (Exception e)
{
logger.error("语法错误出错,无法解析",e)
//接收到非法命令,断开连接
socket.close()
break
}
logger.debug(this.getName()+"退出")
应该没有这样严重的。 TCP只有在网络很差的情况下会有些数据丢掉的。 你在局域网应该还不至于俄。
多办是没有处理粘包俄。人家还没有把数据发给你就读取了。读到就会是 00
定协议把。 很简单的俄。 如 包头+数据区域的长度+数据。
这样根据长度来解析数据就不会出现粘包了。