【Java】网络连接中二进制数据的传输

规范信息

规范信息就是让客户端和服务器之间发送的消息遵守一个规范,类似于一个协议。于是,建立一NetMessage类,其中给出消息的各种参数,规定只能发送NetMessage类。这样做可以方便读取和解析,可以从下面代码中体会到。

public class NetMessage {
	//BIN为二进制类型信息,STR为字符串类型信息
	public static final int BIN = 1;
	public static final int STR = 0;

	private ENetCommand command;	//指定这个消息的指令
	private String action;			//指定这个信息的动作
	private int type;				//信息的类型
	private int len;				//信息的长度
	//把传递的消息分为俩种类型:字符串类型和二进制数据。分别用strPara,binPara来存放。
	private String strPara;
	private byte[] binPara;
}

每次发送一个信息,都应该new一个NetMessage,通过一系列的set方法,把信息参数和内容放到这个NetMessage中。并且send()方法只能接受NetMessage类型的参数,这样就做到了信息的规范,即只能发送NetMessage类型。

完善这个类,把他做成工具
重写这个类的toString方法,当一个NetMessage消息需要发送时,真正发送的其实是他的toStringh后的字符串
@Override
	public String toString() {
		StringBuffer buffer = new StringBuffer();
		
		if(type == STR) {
			if(strPara == null) {
				strPara = "";
				binPara = strPara.getBytes();
			}
		}
		if(binPara == null) {
			binPara = new byte[0];
		}
		
		buffer.append(command).append(".")
			.append(action == null ?" ":action).append(".")
			.append(type).append(".")
			.append(len);
		
		return buffer.toString();
	}

注意看:并没有把内容append到最后,也就是说这里是不发送消息的内容的。
根据发送信息的格式,我们可以很轻松的解析信息的参数。
但是!解析不到消息的具体内容

public NetMessage(String message) {
		int index = message.indexOf('.');
		this.command = ENetCommand.valueOf(message.substring(0, index));
		
		message = message.substring(index+1);
		index = message.indexOf('.');
		this.action = message.substring(0, index);
		
		message = message.substring(index+1);
		index = message.indexOf('.');
		this.type = Integer.valueOf(message.substring(0, index));
		
		message = message.substring(index+1);
		index = message.indexOf('.');
		this.len = Integer.valueOf(message.substring(0, index));
	}

二进制数据的传输

传输数据的类型有俩种,字符串类型和二进制类型,真实传输过程中,如果我们还要根据不同的类型制定俩套不同的传输方案,很愚蠢,所以我用一种通用方案。
即:让NetMessage中的strPara,binPara同步(字符串变成字符数组),只需要传输用来存放二进制数据的binPara。
传输过程

  1. 先发送NetMessage类对应字符串(toString();),相当于发送了信息的头部。
  2. 发送信息的具体内容
  3. 接受信息的头部
  4. 根据信息的头部来接受具体的二进制信息
发送信息
public void send(NetMessage message) {
		if(connection == null) {
			return;
		}
		
		DataOutputStream dos = connection.getDos();
		if(dos == null) {
			return;
		}
		
		try {
			dos.writeUTF(message.toString());						//信息头
			dos.write(message.getBinPara(), 0, message.getLen());	//信息具体内容
		} catch (IOException e) {
			//TODO
		}
	}
接收信息
public NetMessage receive() {
		int restLen = 0;
		int length = 0;
		int off = 0;
		if(connection == null) {
			return null;
		}
		DataInputStream dis = connection.getDis();
		if(dis == null) {
			return null;
		}
		
		NetMessage message = null;
		try {
			message = new NetMessage(dis.readUTF());		//接收信息头
			//根据信息头部给出的len定长接受接下来的信息	
			restLen = message.getLen();	
			byte[] arr = new byte[restLen];
			while(restLen > 0) {					
				length = BUFFER_MAX > restLen ? restLen:BUFFER_MAX; 
				dis.read(arr,off,length);
				off += length;
				restLen -= length;
			}
			message.setBinPara(arr);
		} catch (IOException e) {
			//TODO
		}
		return message;
	}

总结

二进制数据的收发,需要解决的是数据的分组和数据长度不确定的问题。
采用数据头+数据的格式,类似于TCP/IP协议的格式,使信息能被很好解析。
对于很长的二进制数据,可以对他进行分组,每个分组都有一个独立的头,独立发送。

你可能感兴趣的:(【Java】网络连接中二进制数据的传输)