最近项目上要求实现与第三方平台进行socket通信,因为第一次接触,客户也只提供了协议接口文档,没有样例说明,很是迷惑。网上搜索了不少资料,关于socket如何建立连接的不少,但是具体关于消息头通过码流方式发送,特别是使用java语言的少之又少,在同事的帮助下,最终得以实现,遂记录之。
接口描述:消息数据由消息头和消息体组成。消息头由9个字节(byte)表示,消息体长度不固定,各类消息不同。消息头的9个字节不能当做字符处理,需要按整型数处理。
组成 | 中文名称 | 英文名称 | 长度/byte | 取值或说明 |
消息头 | 开始标志 | StartSign | 2 | 固定为0xFFFF,消息开始标识 |
消息类型 | msgType | 1 | 单字节整型数,类型编码含义如下: 0:realTime 1:reqLogin 2:ackLogin 3:reqSyncMsg 4:ackSyncMsg 8:reqHeartBeat 9:ackHeartBeat 10:closeConnAlarm | |
秒时间戳 | timeStamp | 4 | 4字节整型数,字节顺序为Big-Endian,表示消息产生时间,为距离1970-01-01 00:00:00时间偏移的秒数。 | |
长度 | lenOfBody | 2 | 2字节整型数,字节顺序为Big-Endian,表示消息体字节长度,取值范围0~32767。 | |
消息体 | 具体消息内容。对于上报的消息realTime,消息体中只包括一条json格式的数据。 |
实现方式如下:
package test;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class TestHead {
/**
* Big-Endian,将int数值转换为占四个字节的byte数组,本方法适用于(高位在前,低位在后)的顺序。
*/
public static byte[] intToBytes2(int value)
{
byte[] src = new byte[4];
src[0] = (byte) ((value>>24) & 0xFF);
src[1] = (byte) ((value>>16)& 0xFF);
src[2] = (byte) ((value>>8)&0xFF);
src[3] = (byte) (value & 0xFF);
return src;
}
public static int bytesToInt2(byte[] src, int offset) {
int value;
value = (int) ( ((src[offset] & 0xFF)<<24)
|((src[offset+1] & 0xFF)<<16)
|((src[offset+2] & 0xFF)<<8)
|(src[offset+3] & 0xFF));
return value;
}
/**
* Big-Endian,将short数值转换为占二个字节的byte数组,本方法适用于(高位在前,低位在后)的顺序。
*/
public static byte[] shortToBytes2(short value)
{
byte[] src = new byte[2];
src[0] = (byte) ((value>>8)&0xFF);
src[1] = (byte) (value & 0xFF);
return src;
}
public static short bytesToShort2(byte[] src, int offset) {
short value;
value = (short) (
((src[offset] & 0xFF)<<8)
|(src[offset+1] & 0xFF));
return value;
}
/**
* 单字节处理为字节数组
*/
public static byte[] byteToBytes2(byte value){
byte[] src = new byte[1];
src[0] = value;
return src;
}
public static byte bytesToByte(byte[] src, int offset) {
byte value;
value = (src[offset]);
return value;
}
public static void main(String[] args) throws IOException {
//拼接
String strBody = "reqLogin;user=yiy;key=qw#$@;type=msg";
byte[] allMessage = new byte[9+strBody.length()];
short startSign = (short) 0xFFFF;
byte msgType = 1;
int timeStamp = (int) (System.currentTimeMillis()/1000);
short bodyLen = (short) strBody.length();
System.arraycopy(shortToBytes2(startSign),0, allMessage,0,2);
System.arraycopy(byteToBytes2(msgType),0, allMessage,2,1);
System.arraycopy(intToBytes2(timeStamp),0, allMessage,3,4);
System.arraycopy(shortToBytes2(bodyLen),0, allMessage,7,2);
System.arraycopy(strBody.getBytes(),0, allMessage,9,strBody.length());
System.out.println("startSign="+startSign+",msgType="+msgType+",timeStamp="+timeStamp+",bodyLen="+bodyLen+",strBody="+strBody);
//生成文件确认内容
File f = new File("d:" + File.separator + "test.txt");
OutputStream out = null;
out = new FileOutputStream(f);
out.write(allMessage);
out.close();
//解析
short startSignParser = bytesToShort2(allMessage,0);
byte msgTypeParser = bytesToByte(allMessage,2);
int timeStampParser = bytesToInt2(allMessage,3);
short bodyLenParser = bytesToShort2(allMessage,7);
byte[] bodyParser = new byte[bodyLenParser];
System.arraycopy(allMessage,9,bodyParser,0,bodyLenParser);
String bodyParserStr = new String(bodyParser);
System.out.println("startSignParser="+startSignParser+",msgTypeParser="+msgTypeParser+",timeStampParser="+timeStampParser+",bodyLenParser="+bodyLenParser+",bodyParserStr="+bodyParserStr);
}
}