socket接口,数据传输以16进制码流的形式
1.建立连接(鉴权)
2.消息发送
write,flush;write,flush即可
注意:以NULL结束的,因为传输过程中是16进制的码流,而NULL16进制为00,那么直接补00即可,具体方式
byte [] byte = {0};
out.write(byte);//输出流 out = new DataOutputStream(socket.getOutputStream());
1个字节的无符号整数
byte [] byte = {值};
out.write(byte);//输出流 out = new DataOutputStream(socket.getOutputStream());
基于tcp的socket消息由head和体构成:
1.tcp发消息传输过程中为16进制的码流,那么需要以字节流的形式发送
public class SocketUtils {
public static int send(MsgBindHead bind, MsgSendBody send) {
try {
Socket socket;
DataOutputStream out;
socket = new Socket("ip", port);
// 客户端读取数据流
BufferedInputStream in = new BufferedInputStream(socket.getInputStream());
// 向服务器端发送数据
out = new DataOutputStream(socket.getOutputStream());
// 客户端发送数据连接
System.out.println("bind socket开始发送消息...\t");
// 头
System.out.println("绑定头信息:...长度" + bind.getLen());
byte[] intToByteArray1 = TurnOffUtils.intToByteArray1(bind.getLen());// int转为字节数组
byte[] intToByteArray2 = TurnOffUtils.intToByteArray1(bind.getId());
byte[] intToByteArray3 = TurnOffUtils.intToByteArray1(bind.getSeq());
byte[] k = { 0 };
byte[] byteMergerAll = TurnOffUtils.byteMergerAll(intToByteArray1, intToByteArray2, intToByteArray3,
bind.getSys_id().getBytes(), k, TurnOffUtils.getSha1(bind.getPwd()));
out.write(byteMergerAll);
out.flush();//发送
// 客户端读取数据
byte[] result = new byte[16];
int read = in.read(result);
int r = -2;
System.out.println("bind socket客户端收到的数据...长度=【" + read + "】内容:" + new String(result));
for (byte b : result) {
System.out.println(" ");
System.out.print(b);
}
byte[] pro = { 32 };
byte[] pro1 = { 0 };// 补充0
/* 更新方式... */
byte[] b1 = new byte[1];
if (send.getUpdateType() == 1) {
b1[0] = 1;// 增加
}
if (send.getUpdateType() == 3) {
b1[0] = 3;// 更新方式
}
/* 头 +体 code phone+00 时间 方式 */
byte[] protect_no = TurnOffUtils.byteMergerAll(TurnOffUtils.intToByteArray1(send.getLen()),
TurnOffUtils.intToByteArray1(send.getId()), TurnOffUtils.intToByteArray1(send.getNumber()), pro,
send.getProtect_Num().getBytes(), pro1, send.getTime().getBytes(), b1);
out.write(protect_no);
out.flush();
result = new byte[16];
read = in.read(result);
System.out.println("protect socket客户端收到的数据...长度=【" + read + "】内容:" + new String(result));
for (byte b : result) {
System.out.println(" ");
System.out.print(b);
}
out.close();
in.close();
socket.close();
return result[13];
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return -1;
}
/*
* byte[]合并
*/
public static byte[] byteMergerAll(byte[]... values) {
int length_byte = 0;
for (int i = 0; i < values.length; i++) {
length_byte += values[i].length;
}
byte[] all_byte = new byte[length_byte];
int countLength = 0;
for (int i = 0; i < values.length; i++) {
byte[] b = values[i];
System.arraycopy(b, 0, all_byte, countLength, b.length);
countLength += b.length;
}
return all_byte;
}
2.消息长度计算(消息长度,id,序列数 都是占4个字节,16进制数直接用byte字节发送即可)
消息长度如果为头加体的长度,计算方式为,消息体转为16进制的字符串,然后length/2即为字节数,再加上消息头的长度即为消息长度;(16进制的位数(16进制的string长度)除以2就是字节数,即为消息长度)
/*字符串转为16进制字符串*/
public static String strTo16(String s) {
String str = "";
for (int i = 0; i < s.length(); i++) {
int ch = (int) s.charAt(i);
String s4 = Integer.toHexString(ch);
str = str + s4;
}
return str;
}
3.连接中的密码加密为sha-1散列方式加密,但是一般的加密完毕之后都是字符串类型,这里需要的字节类类型,其实在研究底层源码之后稍作修改即可
/*
* sha-1散列加密返回字节流byte
*/
public static byte[] getSha1(String str) {
byte[] buf = new byte[16];
if (null == str || 0 == str.length()) {
return null;
}
byte[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
try {
MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
mdTemp.update(str.getBytes("UTF-8"));
byte[] md = mdTemp.digest();
return md;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
4.消息接收
byte[] result = new byte[16];// 65535 这里返回的消息长度只有13 那么我暂时用16位来接收
int read = in.read(result);
int r = -2;
System.out.println("bind socket客户端收到的数据...长度=【" + read + "】内容:" + new String(result) );
for (byte b : result) {
System.out.print(b);
}
// 具体的消息内容获取
result[index]
总结:tcp协议中,数据的传输过程中是以16进制的码流实现的,那么消息长度就是16进制码流的字节长度(两位一字节);消息发送均以byte字节流的形式发送;