我们选用的流是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 }
这里只是简单的判断一下是否为最后一个分片,可以在此基础上加上更严谨的判断。
谢谢您的阅读,希望对您有些帮助。