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 }

这里只是简单的判断一下是否为最后一个分片,可以在此基础上加上更严谨的判断。

谢谢您的阅读,希望对您有些帮助。