Java socket 以byte[]简单分片传送数据("UTF-8"编码)
我们选用的流是DataOutputStream和DataInputStream,下次再详解java中的各种流的区别。
1.我们先创建对象:
1 private DataOutputStream outputStream = null; 2 private DataInputStream inputStream = null;
2.然后可在构造方法中使用传入的socket对刚创建的对象定义:
1 public ClientHandleThread(Socket socket) { 2 this.socket = socket; 3 this.initTimer(); 4 try { 5 // socket.setSoTimeout(10000); 6 // writer = new BufferedWriter(new OutputStreamWriter( 7 // this.socket.getOutputStream(), "UTF-8")); 8 // reader = new BufferedReader(new InputStreamReader( 9 // this.socket.getInputStream(), "UTF-8")); 10 11 outputStream = new DataOutputStream(this.socket.getOutputStream()); 12 inputStream = new DataInputStream(this.socket.getInputStream()); 13 14 15 } catch (Exception e) { 16 e.printStackTrace(); 17 LogUtil.ERROR(e.getMessage()); 18 } 19 }
3.发送方法定义:
简单的分片格式为:
定义一个byte数组 byte[] buffer = new byte[1024];
该数据中第一个byte作为分片定义格式存储:
/** * 00000000 * 最高位代表是否是第一个分片,为‘1’代表是第一个分片 * 次高位代表是否是最后一个分片,为‘1’代表为最后一个分片 */ buffer[0] |= 0X80;//表示是第一个分片
buffer[0] |= 0X40;//表示是最后一个分片
当然,还可以依据需要加上具体的定义,可以参考网络协议的报头进行设计,有需要可以查看《计算机网络》一书。
该方法分为三种走向:
当数据byte数组bytes的大小-> 0<bytes.length<=1023 时:不用分片,直接定义该片为最后一片buffer[0] |= 0X40;//表示是最后一个分片,直接发送
当数据byte数组bytes的大小-> 1023<bytes.length<=2046时,需要分为两片
当数据byte数组bytes的大小-> 2046<bytes.length时,首先要切出首片(1023大小),然后依据while(remainSize>bufferSize)循环切出中间片,最后剩下的数据量大小<=1023,这作为最后一个分片。
具体的可以参考下列代码:
1 // 发送 2 public void send(String data) { 3 try { 4 //需要设置"UTF-8"编码,避免中文造成的乱码 5 byte[] bytes = (data + "\r\n").getBytes("UTF-8"); 6 int posotion = 0; 7 int remainSize = bytes.length;//剩余数据量大小 8 int bufferSize = 1023;//缓冲区数据量大小+1 9 if(remainSize > bufferSize) 10 { 11 remainSize -=bufferSize; 12 byte[] buffer = new byte[1024]; 13 buffer[0] = 0;//初始化 14 /** 15 * 00000000 16 * 最高位代表是否是第一个分片,为‘1’代表是第一个分片 17 * 次高位代表是否是最后一个分片,为‘1’代表为最后一个分片 18 */ 19 buffer[0] |= 0X80;//表示是第一个分片 20 System.arraycopy(bytes, posotion, buffer, 1, bufferSize); 21 posotion += bufferSize; 22 this.outputStream.write(buffer); 23 this.outputStream.flush(); 24 25 } 26 while (remainSize>bufferSize) { 27 remainSize -= bufferSize; 28 byte[] buffer = new byte[1024]; 29 buffer[0] = 0;//初始化 30 // buffer[0] |= 0X80;//表示是第一个分片 31 // buffer[0] |= 0X40;//表示是最后一个分片 32 System.arraycopy(bytes, posotion, buffer, 1, bufferSize); 33 posotion += bufferSize; 34 this.outputStream.write(buffer); 35 this.outputStream.flush(); 36 37 } 38 if(remainSize > 0) 39 { 40 byte[] buffer = new byte[remainSize+1]; 41 buffer[0] = 0;//初始化 42 // buffer[0] |= 0X80;//表示是第一个分片 43 buffer[0] |= 0X40;//表示是最后一个分片 44 System.arraycopy(bytes, posotion, buffer, 1, remainSize); 45 this.outputStream.write(buffer); 46 this.outputStream.flush(); 47 } 48 49 // this.writer.write(data + "\r\n"); 50 // this.writer.flush(); 51 System.out.println("发送"+data); 52 } catch (IOException e) { 53 LogUtil.ERROR(e.getMessage()); 54 e.printStackTrace(); 55 } 56 57 }
4.下面是接收处理代码:
需要表达的一点是,socket会依据切片的顺序发送,一般不会造成切片的顺序颠倒,当然严谨一些更好,最好增加数据包的序列号和编号。
下面只是一个简单示例:
1 try { 2 // System.out.println(RunFlag); 3 4 //char chars[] = new char[1024]; 5 byte bytes[] = new byte[1024]; 6 int len = 0; 7 StringBuilder jsonBuffer = new StringBuilder(); 8 String temp = null; 9 int index = 0; 10 // while ((len = reader.read(chars)) != -1) { 11 // temp = new String(chars, 0, len); 12 // if ((index = temp.indexOf("\n")) != -1) {// 遇到\n时就结束接收 13 // jsonBuffer.append(temp.substring(0, index)); 14 // break; 15 // } 16 // jsonBuffer.append(temp); 17 // } 18 19 20 while ((len = inputStream.read(bytes)) != -1) { 21 temp = new String(bytes, 1, len-1,"UTF-8"); 22 if ((index = temp.indexOf("\n")) != -1 && (bytes[0] &= 0X40)==0X40) {// 遇到\n时就结束接收和最后一个分片 23 jsonBuffer.append(temp.substring(0, index)); 24 break; 25 } 26 jsonBuffer.append(temp); 27 } 28 29 30 String jsonString = jsonBuffer.toString(); 31
......
32 } catch (Exception e) { 33 LogUtil.ERROR(e.toString()); 34 }
这里只是简单的判断一下是否为最后一个分片,可以在此基础上加上更严谨的判断。
谢谢您的阅读,希望对您有些帮助。