java socket报文通信(二)报文的封装

昨天我们谈了怎么建立socket通信的服务端和客户端,今天我们就来谈一谈怎么封装报文。

什么是报文这里我就不在阐述了,不清楚的朋友可以自己去查资料。我们今天要谈的报文主要友以下几个部分组成:

3位同步校验位+8位报文长度+报文头+报文体+32位MD5校验位

基本格式如下:

0X110X120X1300000232<?xml version="1.0" encoding="GBK"?><ROOT><Code>0204</Code><Date>20141223</Date><No>141223010008152</No><Code>17010001</Code><Name>张三</Name></ROOT>B251AB76B11114DB176023A0AA27A524

说明:

  前面的0X110X120X13是3位16进制的同部位,这里为了大家理解,所以就以字符的形式谢出来了。00000232是报文长度。<?xml version="1.0" encoding="GBK"?><ROOT><Code>0204</Code><Date>20141223</Date><No>141223010008152</No><Code>17010001</Code></ROOT>是报文头。即每个报文都包含的信息。<Name>张三</Name>是报文体。B251AB76B11114DB176023A0AA27A524是加密数据。

关于如何将对象转换为xml格式的报文我将在下一篇写,这里主要是给大家如何将如上的这些字符串转化为字节以及如何发送和接收报文。

1.建立报文的对象

public class SocketPacket {

    private String bodyLen;
    private String body;
    private String syncStr;
    private String md5;
    public String getBodyLen() {
        return bodyLen;
    }
    public String getBody() {
        return body;
    }
    public String getSyncStr() {
        return syncStr;
    }
    public String getMd5() {
        return md5;
    }
    public void setBodyLen(String bodyLen) {
        this.bodyLen = bodyLen;
    }
    public void setBody(String body) {
        this.body = body;
    }
    public void setSyncStr(String syncStr) {
        this.syncStr = syncStr;
    }
    public void setMd5(String md5) {
        this.md5 = md5;
    }

    public byte[] getByteStream() throws UnsupportedEncodingException{
        byte[] bodyBytes = this.body.getBytes("gbk");//获得body的字节数组
        int bodyLength = bodyBytes.length;
        int socketLength = 3+bodyLength+8+32;
        byte [] soc = new byte[socketLength];
        //添加校验数据
        int index = 0;
        soc[0]=0x11;
        soc[1]=0x12;
        soc[2]=0x13;
        index+=3;
        //添加8位报文长度(我的博文中也有NumberFormat的用法介绍)
        NumberFormat numberFormat = NumberFormat.getNumberInstance();
        numberFormat.setMinimumIntegerDigits(8);
        numberFormat.setGroupingUsed(false);
        byte [] num = numberFormat.format(socketLength).getBytes();
        for(int i = 0;i<8;i++){
            soc[index++]= num[i];
        }
        //添加body内容
        for(int i = 0;i<bodyLength;i++){
            soc[index++] = bodyBytes[i];
        }
        //添加md5校验码
        byte [] md5Bytes = this.md5.getBytes();
        for (int i = 0; i < num.length; i++) {
            soc[index++] = md5Bytes[i];
        }
        return soc;
    }

    //字节装转报文string
    public String getString(byte [] socketBytes){
        String syncStr = this.bytesToString(socketBytes, 0, 3);
        String socketLength = this.bytesToString(socketBytes, 3, 3+8);
        String body = this.bytesToString(socketBytes, 3+8, socketBytes.length-32);
        String md5 = this.bytesToString(socketBytes,socketBytes.length-32,socketBytes.length);
        return syncStr+socketLength+body+md5;
    }

    //将字节数组转化为string
    public String bytesToString(byte [] bytes,int start,int end){
        String str = "";
        if(bytes.length<end-start){
            return str;
        }
        byte [] bs = new byte[end-start];
        for(int i = 0;i<end-start;i++){
            bs[i] = bytes[start++];
        }
        str = new String(bs);
        return str;
    }

    public String toString(){
        return this.syncStr+this.bodyLen+this.body+this.md5;
    }

}

2.封装发送和接收报文的工具类

/**
 * 报文发送
 */
public class SockeUtil {
    Socket socket = null;
    public SockeUtil(String ip,int port) throws UnknownHostException, IOException{
        socket = new Socket(ip, port);
    }
    //
    public SocketPacket sentSocket(SocketPacket socketPacket) throws UnsupportedEncodingException, IOException{
        SocketPacket sPacket = new SocketPacket();
        OutputStream output=null;
        InputStream input =null;
        // 同步字符串(3byte)
        byte[] sync = null; //
        byte[] bodyLen = null; // 8位长度
        byte[] body = null; // 内容
        byte[] md5 = null;  // MD5
        output = socket.getOutputStream();
        //写数据发送报文
        output.write(socketPacket.getByteStream());
        //获得服务端返回的数据
        input = socket.getInputStream();
        sync = this.streamToBytes(input,3);
        bodyLen = this.streamToBytes(input, 8);
        String lenString = new String(bodyLen);
        int len = Integer.valueOf(lenString);
        body = this.streamToBytes(input, len);
        md5 = this.streamToBytes(input, 32);
        sPacket.setSyncStr(new String(sync,Charset.forName("gbk")));
        socketPacket.setBodyLen(new String(bodyLen,Charset.forName("gbk")));
        socketPacket.setBody(new String(body,Charset.forName("gbk")));
        socketPacket.setMd5(new String(md5,Charset.forName("gbk")));
        return sPacket;
    }

    public byte[] streamToBytes(InputStream inputStream,int len){
        /**
         * inputStream.read(要复制到得字节数组,起始位置下标,要复制的长度)
         * 该方法读取后input的下标会自动的后移,下次读取的时候还是从上次读取后移动到的下标开始读取
         * 所以每次读取后就不需要在制定起始的下标了
         */
        byte [] bytes= new byte[len];
        try {
            inputStream.read(bytes, 0, len);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return bytes;
    }
}

3.在封装一个调用报文发送的类:

public String socket(SocketPackage socketPackage) throws UnsupportedEncodingException{

        SocketClient socketClient=null;;
        try {
            socketClient = new SocketClient(ip,端口);
        } catch (UnknownHostException e) {
            log.error("socket链接异常,链接信息:"+ip+端口);
            e.printStackTrace();
        } catch (IOException e) {
            log.error("socket IO异常");
            e.printStackTrace();
        }
        SocketPackage s = null;
        try {
            s = socketClient.sendMsg(socketPackage);
        } catch (Exception e) {
            try {
                log.error("socket发送消息异常,发送信息:"+new String(socketPackage.getByteStream(),"GBK"));
            } catch (UnsupportedEncodingException e1) {
                log.error("socket将socketPackage转为字符串异常,socketPackage信息:"+socketPackage.getByteStream());
                e1.printStackTrace();
            }
            e.printStackTrace();
        }
        String result = "";
        try {
             result = new  String(s.getStream(),"GBK");
        } catch (UnsupportedEncodingException e) {
            log.error("socket将socketPackage转为字符串异常,socketPackage信息:"+socketPackage.getByteStream());
            e.printStackTrace();
        }
        return result ;
  }

这样我们就能发送报文和接收报文了!赶紧试一下吧!^_^

时间: 2024-10-13 02:42:08

java socket报文通信(二)报文的封装的相关文章

java socket线程通信

关于socket线程通信的一些知识整理 一般我们需要要让两台机子进行通信,需要创建一个Server 类,一个Client类,还需要创建一个线程类 server public class Server { public static void main(String[] args) throws IOException {  ServerSocket ss = new ServerSocket(8888);  int num=0;  System.out.println("服务器即将启动,   等

Java Socket编程----通信是这样炼成的

Java最初是作为网络编程语言出现的,其对网络提供了高度的支持,使得客户端和服务器的沟通变成了现实,而在网络编程中,使用最多的就是Socket.像大家熟悉的QQ.MSN都使用了Socket相关的技术.下面就让我们一起揭开Socket的神秘面纱. Socket编程 一.网络基础知识(参考计算机网络)            关于计算机网络部分可以参考相关博客:           <TCP/IP协议栈及OSI参考模型详解> http://wangdy.blog.51cto.com/3845563/

linux c、java socket json 通信

一.服务端 c++ [email protected]:~/Public/xtranfer$ cat ./main.c #include <stdio.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <unistd.h> #include <stdlib.h> #include <time.h> #incl

Java Socket应用(二)——java中InetAddress的应用

转载请注明:http://blog.csdn.net/uniquewonderq 1.InetAddress类 用于标识网络上的硬件资源,实际主要用来表示IP地址的相关信息. 关于该类的方法可以在API帮助文档查看. 要获取InetAdress类的实例,由于它没有构造方法,但是它有静态方法可以返回该类的实例,所以,可以这样子来获取. 下面简单举一个例子: package com.test; import java.net.InetAddress; import java.net.UnknownH

Java Socket编程基础篇

原文地址:Java Socket编程----通信是这样炼成的 Java最初是作为网络编程语言出现的,其对网络提供了高度的支持,使得客户端和服务器的沟通变成了现实,而在网络编程中,使用最多的就是Socket.像大家熟悉的QQ.MSN都使用了Socket相关的技术.下面就让我们一起揭开Socket的神秘面纱. Socket编程 网络基础知识点: 两台计算机间进行通讯需要以下三个条件 IP地址.协议.端口号: IP地址:定位应用所在机器的网络位置.(比如家庭住址:北京市朝阳区XX街道XX小区) 端口号

java socket小结

Java socket相对与C来说,封装性更好,所以使用上面比较简洁.服务端方面,需要一个ServerSocket对象,开启监听,利用服务端获取的链接服务端的socket对象,构建输入流和输出流,输入流是InputStream input,向上封装后是InputStreamReader inputreader,InputStreamReader对象向上封装后是BufferedReader对象.BufferedReader对象用来获取客户端发送给服务端的信息,输出流对象是OutputStream

java socket报文通信(一)socket的建立

java socket报文通信(一) socket的建立  今天来和大家分享一下java中如何使用socket进行通信.先来啰嗦两句,看看Tcp/ip和udp: TCP是Transfer Control Protocol的 简称,是一种面向连接的保证可靠传输的协议.通过TCP协议传输,得到的是一个顺序的无差错的数据流.发送方和接收方的成对的两个socket之间必须建 立连接,以便在TCP协议的基础上进行通信,当一个socket(通常都是server socket)等待建立连接时,另一个socke

JAVA通信系列一:Java Socket技术总结

本文是学习java Socket整理的资料,供参考. 1       Socket通信原理 1.1     ISO七层模型 1.2     TCP/IP五层模型 应用层相当于OSI中的会话层,表示层,应用层. 区别参考:http://blog.chinaunix.net/uid-22166872-id-3716751.html 1.3     TCP报文 (1)序号:Seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记. (2)确认序号:Ack序号,占32

如何使用socket进行java网络编程(二)

通过在如何使用socket进行java网络编程(一)中程序的编写,可以总结出一些常用的java socket编程的范例来. ServerSocket server = new ServerSocket(_PORT_); while (true) { Socket nextClient = server.accept(); SocketHandler handler = new SocketHandler(nextClient); Thread t = new Thread(handler); t