java 自定义通讯协议

 JAVA默认提供了对file,ftp,gopher,http,https,jar,mailto,netdoc协议的支持。当我们要利用这些协议来创建应用时,主要会涉及到如下几个类:

      1.java.net.URL:URL资源

      2.java.net.URLConnection:各种URL资源连接器

    例如,当我们利用HTTP协议获取Web资源时,通常的过程如下:

 

Java代码   收藏代码
  1. URL url = new URL("http://www.163.com");  
  2. URLConnection conneciotn = url.openConnection();  

 

 

        URL和URLConnection是如何做到对协议支持的呢?在它们的内部,主要涉及到了如下几个类:

        1.URLStreamHandler:协议的流处理器,负责对特定URL协议的解析,并创建符合当前协议的URLConnection;

        2.URLStreamHandlerFactory:协议处理工厂,负责为特定协议找到正确的URLStreamHandler。

        当利用URL对象创建资源时,其构造函数在去掉协议字段后将其传给URLStreamHandlerFactory,由该工厂来接受协议,为该协议找到并创建适当的URLStreamHandler实现类,最后存储在URL对象的一个字段中(即URL类中transient修饰的URLStreamHandler成员属性)。
       URLStreamHandler和URLConnection总是成对出现的。因此,若要实现对新协议的支持时,需同时实现这两个抽象类,分别负责对协议的解析,以及与服务器的交互(数据转换等)。

      另外,JAVA是如何识别当前URL协议该由哪个URLStreamHandler和URLConnection来处理的呢?在创建URL对象时,其内部调用了一个getURLStreamHandler(String protocol)静态方法,它将根据协议的名称来找到对应的URLStreamHandler实现类,其查找规则如下:

     1)检测是否创建了URLStreamHandlerFactory对象:如果创建,则直接使用createURLStreamHandler(String protocol)方法创建的协议处理器,否则进入步骤2);

     2)在java.protocol.handler.pkgs系统属性指定的包中查找与协议同名的子包和名为Handler的类,即负责处理当前协议的URLStreamHandler实现类必须在的<包名>.<协议名定义的包>中,并且类名称必须为Handler。例如:com.company.net.protocol.rdp包中的Handler类将用于处理RDP协议。若仍未找到则进入步骤3);

    3)在JDK rt.jar中的sun.net.www.protocol.<name>包中查找Handler类。例如,若当前协议为ftp,则URL所使用协议处理器就应该为sun.net.www.protocol.ftp包中的Handler类。如下图:
         下面结合一个实例来说明如何开发一个新的网络协议。

          背景:senv(Server Environment Protocol)协议可让客户端连接远程服务器后发送出请求,请求的内容就是URL查询参数部分,该协议的默认端口为9527。例如:senv://192.168.1.101:9527?pro=os.name,java.version表示获取192.168.1.101这台主机的操作系统名和JRE的版本信息,如果没有查询参数,客户端将默认发送一个"?",表示获取所有的系统属性信息。

       
 1.Senv协议处理器

Java代码   收藏代码
  1. package com.daniele.appdemo.net.protocol.custom.senv;  
  2.   
  3. import java.io.IOException;  
  4. import java.net.URL;  
  5. import java.net.URLConnection;  
  6. import java.net.URLStreamHandler;  
  7.   
  8. /** 
  9.  * <p> 
  10.  *      自定义的senv协议处理器。 
  11.  *      由于senv协议的格式符合标准的URL格式: 
  12.  *          protocol://username@hostname:port/path/filename?query#fragment 
  13.  *      因此,这个实现类只需实现父类中的openConnection()方法即可。否则,需重写父类方法 
  14.  *      protected void parseURL(URL u, String spec, int start, int limit), 
  15.  *      来重新正确的设置URL的各个属性值,例如:host,port,query等。 
  16.  * </p>  
  17.  * @author  <a href="mailto:code727@gmail.com">Daniele</a> 
  18.  * @version 1.0.0, 2013-5-8 
  19.  * @see      
  20.  * @since   AppDemo1.0.0 
  21.  */  
  22. public class Handler extends URLStreamHandler {  
  23.   
  24.     /** 
  25.      * <p>当URL根据协议找到该处理器并调用openConnection()方法后,返回负责处理该协议连接的连接器</p>  
  26.      * @author <a href="mailto:code727@gmail.com">Daniele</a>  
  27.      * @param u 
  28.      * @return 
  29.      * @throws IOException  
  30.      * @since AppDemo1.0.0 
  31.      */  
  32.     @Override  
  33.     protected URLConnection openConnection(URL u) throws IOException {  
  34.         return new SenvURLConnection(u);  
  35.     }  
  36.       
  37. }  

 2.Senv协议连接器

Java代码   收藏代码
  1. package com.daniele.appdemo.net.protocol.custom.senv;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5. import java.io.OutputStream;  
  6. import java.net.Socket;  
  7. import java.net.URL;  
  8. import java.net.URLConnection;  
  9.   
  10. import com.daniele.appdemo.util.StringUtils;  
  11.   
  12. /** 
  13.  * <p>自定义senv协议连接器</p>  
  14.  * @author  <a href="mailto:code727@gmail.com">Daniele</a> 
  15.  * @version 1.0.0, 2013-5-8 
  16.  * @see      
  17.  * @since   AppDemo1.0.0 
  18.  */  
  19. public class SenvURLConnection extends URLConnection {  
  20.       
  21.     /** senv协议的默认端口号 */  
  22.     public static final int DEFAULT_PORT = 9527;  
  23.       
  24.     private Socket connection = null;  
  25.   
  26.     public SenvURLConnection(URL url) {  
  27.         super(url);  
  28.     }  
  29.       
  30.     /** 
  31.      * <p>由于父类URLConnection中的getInputStream()方法不提供输入流的获取实现逻辑,因此这里需要重写此方法</p>  
  32.      * @author <a href="mailto:code727@gmail.com">Daniele</a>  
  33.      * @return 
  34.      * @throws IOException  
  35.      * @since AppDemo1.0.0  
  36.      */  
  37.     @Override  
  38.     public synchronized InputStream getInputStream() throws IOException {  
  39.         if (!connected)  
  40.             this.connect();  
  41.         return connection.getInputStream();  
  42.     }  
  43.       
  44.     /** 
  45.      * <p>senv协议连接操作</p>  
  46.      * @author <a href="mailto:code727@gmail.com">Daniele</a>  
  47.      * @throws IOException  
  48.      * @since AppDemo1.0.0  
  49.      */  
  50.     @Override  
  51.     public synchronized void connect() throws IOException {  
  52.         if (!connected) {  
  53.             int port = url.getPort();  
  54.             if (port < 1 || port > 65535)  
  55.                 port = DEFAULT_PORT;  
  56.             this.connection = new Socket(url.getHost(), port);  
  57.             connected = true;  
  58.             // 连接后立即发送请求  
  59.             sendRequest(url);  
  60.         }  
  61.     }  
  62.       
  63.     /** 
  64.      * <p>发送senv协议请求</p>  
  65.      * @author <a href="mailto:code727@gmail.com">Daniele</a>  
  66.      * @param u 
  67.      * @throws IOException  
  68.      * @since AppDemo1.0.0 
  69.      */  
  70.     protected void sendRequest(URL u) throws IOException {  
  71.         OutputStream outputStream = this.connection.getOutputStream();  
  72.           
  73.         String queryString = u.getQuery();  
  74.           
  75.         /* 
  76.          *  将URL的查询参数部分发送给服务器,由服务器负责解析查询后返回结果。 
  77.          *  当参数参数部分为空时,则发送一个"?",表示查询服务器系统环境的所有信息。 
  78.          */  
  79.         outputStream.write(StringUtils.isNotNullOrBlank(queryString)? queryString.getBytes() : "?".getBytes());  
  80.         outputStream.flush();  
  81.     }  
  82.   
  83. }  

 

3.协议处理器工厂

Java代码   收藏代码
  1. package com.daniele.appdemo.net.protocol.factory;  
  2.   
  3. import java.net.URLStreamHandler;  
  4. import java.net.URLStreamHandlerFactory;  
  5.   
  6. /** 
  7.  * <p> 
  8.  *       自定义协议的处理器工厂,负责针对每种自定义的协议而返回它们各自对应的协议处理器 
  9.  *       如果要用上述的查找规则1来安装协议处理器时,则需要用到这个类 
  10.  *</p>  
  11.  * @author  <a href="mailto:code727@gmail.com">Daniele</a> 
  12.  * @version 1.0.0, 2013-5-9 
  13.  * @see      
  14.  * @since   AppDemo1.0.0 
  15.  */  
  16. public class CustomProtocolFactory implements URLStreamHandlerFactory {  
  17.   
  18.     public URLStreamHandler createURLStreamHandler(String protocol) {  
  19.         if ("senv".equalsIgnoreCase(protocol))  
  20.             return new com.daniele.appdemo.net.protocol.custom.senv.Handler();  
  21.         return null;  
  22.     }  
  23.   
  24. }  

 

4.处理Senv协议的服务器

Java代码   收藏代码
  1. package com.daniele.appdemo.net.protocol.test;  
  2.   
  3. import java.io.IOException;  
  4. import java.net.InetAddress;  
  5. import java.net.InetSocketAddress;  
  6. import java.nio.ByteBuffer;  
  7. import java.nio.channels.SelectionKey;  
  8. import java.nio.channels.Selector;  
  9. import java.nio.channels.ServerSocketChannel;  
  10. import java.nio.channels.SocketChannel;  
  11. import java.nio.charset.Charset;  
  12. import java.nio.charset.CharsetDecoder;  
  13. import java.util.Iterator;  
  14.   
  15. import org.apache.log4j.Logger;  
  16.   
  17. import com.daniele.appdemo.util.StringUtils;  
  18. import com.daniele.appdemo.util.SystemUtils;  
  19.   
  20. /** 
  21.  * <p>处理Senv协议的服务器 
  22.  *    1.接收客户端请求 
  23.  *    2.发送响应结果 
  24.  *  </p>  
  25.  * @author  <a href="mailto:code727@gmail.com">Daniele</a> 
  26.  * @version 1.0.0, 2013-5-10 
  27.  * @see      
  28.  * @since   AppDemo1.0.0 
  29.  */  
  30.   
  31. public class SenvProtocolServer {  
  32.       
  33.     private static final Logger logger = Logger.getLogger(SenvProtocolServer.class);  
  34.       
  35.     /** Senv协议的请求参数标识 */  
  36.     public static final String REQUEST_PARAM_MARK = "pro=";  
  37.       
  38.     /** Senv协议服务的默认端口号 */  
  39.     private static final int DEFAULT_PORT = 9527;  
  40.   
  41.     /** 服务器的IP或主机名 */  
  42.     private String host;  
  43.       
  44.     /** 绑定了Senv协议服务的端口号 */  
  45.     private int port = 9527;  
  46.       
  47.     /** 当前就绪的服务端通道 */  
  48.     private ServerSocketChannel serverChannel;  
  49.       
  50.     /** 当前就绪的客户端通道 */  
  51.     private SocketChannel clientChannel;  
  52.       
  53.     /** 服务端的事件注册器 */  
  54.     private Selector selector;  
  55.       
  56.     /** 
  57.      * <p>启动Senv协议服务器</p>  
  58.      * @author <a href="mailto:code727@gmail.com">Daniele</a>  
  59.      * @throws IOException  
  60.      * @since AppDemo1.0.0 
  61.      */  
  62.     public void start() throws IOException {  
  63.           
  64.         serverChannel = ServerSocketChannel.open();  
  65.           
  66.         if (port < 1 || port > 65535)  
  67.             port = DEFAULT_PORT;  
  68.           
  69.         if (StringUtils.isNotNullOrBlank(host)) {  
  70.             serverChannel.socket().bind(new InetSocketAddress(InetAddress.getByName(host), port));  
  71.             logger.info("Start server " + host + ":" + port);  
  72.         } else {  
  73.             serverChannel.socket().bind(new InetSocketAddress(port));  
  74.             logger.info("Start server on port " + port);  
  75.         }  
  76.         serverChannel.configureBlocking(false);  
  77.         selector = Selector.open();  
  78.         serverChannel.register(selector, SelectionKey.OP_ACCEPT);   
  79.         handle();  
  80.     }  
  81.       
  82.     /** 
  83.      * <p>处理Senv协议请求</p>  
  84.      * @author <a href="mailto:code727@gmail.com">Daniele</a>  
  85.      * @throws IOException  
  86.      * @since AppDemo1.0.0 
  87.      */  
  88.     protected void handle() throws IOException {  
  89.         while (true) {  
  90.             selector.select();  
  91.             Iterator<SelectionKey> keySetIterator = selector.selectedKeys().iterator();  
  92.             SelectionKey cuurentKey = null;  
  93.             while (keySetIterator.hasNext()) {  
  94.                 // 获取当前就绪通道的键对象  
  95.                 cuurentKey = keySetIterator.next();  
  96.                 // 避免同一个就绪通道被重复处理  
  97.                 keySetIterator.remove();  
  98.                 try {  
  99.                     if (cuurentKey.isAcceptable()) {  
  100.                         serverChannel = (ServerSocketChannel) cuurentKey.channel();  
  101.                         clientChannel = serverChannel.accept();  
  102.                         if (clientChannel != null) {  
  103.                             logger.info("Receive request from "   
  104.                                     + clientChannel.socket().getInetAddress().getHostAddress() + ":"  
  105.                                     + clientChannel.socket().getLocalPort());  
  106.                             clientChannel.configureBlocking(false);  
  107.                             clientChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);  
  108.                         }   
  109.                     } else {  
  110.                         clientChannel = (SocketChannel) cuurentKey.channel();  
  111.                         if (cuurentKey.isReadable())   
  112.                             writeResponse();  
  113.                     }  
  114.                 } catch (IOException e) {  
  115.                     if (clientChannel != null && clientChannel.isOpen())  
  116.                         try {  
  117.                             /* 
  118.                              *  为防止服务端在读写客户端信息时,客户端由于某种原因被意外关闭引起服务端也被强制关闭的情况发生。 
  119.                              *  需在catch块中也需要对客户端的通道做关闭处理, 从而防止服务端也被强制关闭的严重问题。 
  120.                              *  另外,对就绪通道的读写过程需单独的在一个try...catch块中。 
  121.                              */  
  122.                             clientChannel.close();  
  123.                         } catch (IOException ioe) {  
  124.                             ioe.printStackTrace();  
  125.                         }  
  126.                 }   
  127.             }  
  128.         }  
  129.     }  
  130.       
  131.     /** 
  132.      * <p>读取客户端请求</p>  
  133.      * @author <a href="mailto:code727@gmail.com">Daniele</a>  
  134.      * @return  
  135.      * @throws IOException  
  136.      * @throws   
  137.      * @since AppDemo1.0.0 
  138.      */  
  139.     protected String readRequest() throws IOException {  
  140.         StringBuffer request = new StringBuffer();  
  141.         CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();  
  142.         ByteBuffer buffer = ByteBuffer.allocate(1024);  
  143.         while (clientChannel.read(buffer) > 0) {  
  144.             buffer.flip();  
  145.             request.append(decoder.decode(buffer).toString());  
  146.             buffer.clear();  
  147.         }  
  148.         return request.toString();  
  149.     }  
  150.       
  151.     /** 
  152.      * <p>向客户端返回响应结果</p>  
  153.      * @author <a href="mailto:code727@gmail.com">Daniele</a>  
  154.      * @throws IOException  
  155.      * @since AppDemo1.0.0 
  156.      */  
  157.     protected void writeResponse() throws IOException {  
  158.         String request = readRequest();  
  159.         int start = -1;  
  160.         // 如果发送的请求为"?"或请求中无指定的参数时,则查询所有的系统环境属性  
  161.         if ("?".equals(request) ||   
  162.                 (start = request.toLowerCase().indexOf(REQUEST_PARAM_MARK)) < 0) {  
  163.             clientChannel.write(ByteBuffer.wrap(SystemUtils.formatSystemProperties().getBytes()));  
  164.         } else {  
  165.             // 获取请求参数值  
  166.             String queryValueString = request.substring(start + REQUEST_PARAM_MARK.length());  
  167.             if (StringUtils.isNullOrBlank(queryValueString))  
  168.                 clientChannel.write(ByteBuffer.wrap(SystemUtils.formatSystemProperties().getBytes()));  
  169.             else {  
  170.                 int index = queryValueString.indexOf("&");  
  171.                 if (index > -1)  
  172.                     /* 
  173.                      *  如果请求参数值里出现了"&"字符, 
  174.                      *  则说明这个字符后面的内容则认为是其它一些请求参数的内容, 
  175.                      *  因此不对这部分内容作处理 
  176.                      */  
  177.                     queryValueString = queryValueString.substring(0, index);  
  178.                 clientChannel.write(ByteBuffer.wrap(SystemUtils.formatSystemProperties(queryValueString.split(",")).getBytes()));  
  179.             }  
  180.         }  
  181.         /* 
  182.          *  响应内容被发送出去之后添加换行标识, 
  183.          *  目的是让客户端的BufferedReader对象调用readLine()方法后能将当前行的内容读取出来 
  184.          */  
  185.         clientChannel.write(ByteBuffer.wrap("\n".getBytes()));  
  186.           
  187.         /* 
  188.          *  发送完响应信息后马上关闭与客户端之间的通道。 
  189.          *  目的在于让客户端读取完这些响应之后,就立即释放掉资源,从而让读操作不会一直处于阻塞状态 
  190.          */  
  191.         clientChannel.close();  
  192.     }  
  193.     public String getHost() {  
  194.         return host;  
  195.     }  
  196.   
  197.     public void setHost(String host) {  
  198.         this.host = host;  
  199.     }  
  200.   
  201.     public int getPort() {  
  202.         return port;  
  203.     }  
  204.   
  205.     public void setPort(int port) {  
  206.         this.port = port;  
  207.     }  
  208.   
  209.     public static void main(String[] args) {  
  210.         SenvProtocolServer server = new SenvProtocolServer();  
  211.         server.setHost("192.168.1.101");  
  212.         try {  
  213.             server.start();  
  214.         } catch (IOException e) {  
  215.             e.printStackTrace();  
  216.         }  
  217.     }  
  218.   
  219. }  

 

 4.Senv协议请求客户端

Java代码   收藏代码
  1. /** 
  2.  * <p> 
  3.  *    Senv协议请求的客户端,主要功能分为: 
  4.  *    1.在创建第一次创建URL对象之前,添加对自定义协议的支持 
  5.  *    2.发送请求 
  6.  *    3.展示响应数据 
  7.  * </p>  
  8.  * @author  <a href="mailto:code727@gmail.com">Daniele</a> 
  9.  * @version 1.0.0, 2013-5-9 
  10.  * @see      
  11.  * @since   AppDemo1.0.0 
  12.  */  
  13.   
  14. public class SenvProtocolClient {  
  15.       
  16.     public static void main(String[] args) {  
  17.         BufferedReader reader = null;  
  18.         try {  
  19.             // 配置协议处理器查找规则一  
  20.             if (StringUtils.isNullOrBlank(System.getProperty("java.protocol.handler.pkgs"))) {  
  21.                 // 设置各个协议包所在的父包路径  
  22.                 System.setProperty("java.protocol.handler.pkgs""com.daniele.appdemo.net.protocol.custom");  
  23.             }  
  24.             /* 
  25.                          * 配置协议处理器查找规则二 
  26.                          * 这种方式在整个应用范围之内只能被执行一次。 
  27.                          * 如果多于一次则会出现"java.lang.Error: factory already defined"这样的错误。但不会受规则一的限制. 
  28.                          */   
  29. //          URL.setURLStreamHandlerFactory(new CustomProtocolFactory());  
  30.               
  31.             URL url = new URL("senv://192.168.1.101:9527/");  
  32.             reader = new BufferedReader(new InputStreamReader(url.openConnection().getInputStream()));  
  33.             String result = "";  
  34.             while ((result = reader.readLine()) != null)  
  35.                 System.out.println(result);  
  36.         } catch (IOException e) {  
  37.             e.printStackTrace();  
  38.         } finally {  
  39.             try {  
  40.                 if (reader != null)  
  41.                     reader.close();  
  42.             } catch (IOException e) {  
  43.                 e.printStackTrace();  
  44.             }  
  45.         }  
  46.     }  
  47.   
  48. }  

 

Java代码   收藏代码
  1. package com.daniele.appdemo.util;  
  2.   
  3. import java.util.Enumeration;  
  4. import java.util.Properties;  
  5.   
  6. /** 
  7.  * <p>运行环境工具类</p>  
  8.  * @author  <a href="mailto:code727@gmail.com">Daniele</a> 
  9.  * @version 1.0.0, 2013-5-9 
  10.  * @see      
  11.  * @since   AppDemo1.0.0 
  12.  */  
  13.   
  14. public class SystemUtils {  
  15.       
  16.     private static Properties properties = null;  
  17.       
  18.     static {  
  19.         properties = System.getProperties();  
  20.     }  
  21.       
  22.     /** 
  23.      * <p>返回格式化后的所有系统属性信息</p>  
  24.      * @author <a href="mailto:code727@gmail.com">Daniele</a>  
  25.      * @return  
  26.      * @since AppDemo1.0.0 
  27.      */  
  28.     @SuppressWarnings("unchecked")  
  29.     public static String formatSystemProperties() {  
  30.         StringBuffer formatResult = new StringBuffer();  
  31.         Enumeration<String> names = (Enumeration<String>) properties.propertyNames();  
  32.         while (names.hasMoreElements()) {  
  33.             String name = names.nextElement();  
  34.             formatResult.append(name).append("=")  
  35.                 .append(properties.getProperty(name)).append("\n");  
  36.         }  
  37.         int length = 0;  
  38.         return (length = formatResult.length()) > 0 ?   
  39.                 formatResult.substring(0, length - 1) : "";  
  40.     }  
  41.       
  42.     /** 
  43.      * <p>返回格式化后的所有指定的系统属性信息</p>  
  44.      * @author <a href="mailto:code727@gmail.com">Daniele</a>  
  45.      * @param propertyKeys 
  46.      * @return  
  47.      * @since AppDemo1.0.0 
  48.      */  
  49.     public static String formatSystemProperties(String[] propertyKeys) {  
  50.         StringBuffer formatResult = new StringBuffer();  
  51.         if (propertyKeys != null && propertyKeys.length > 0) {  
  52.             for (String key : propertyKeys)   
  53.                 formatResult.append(key).append("=")  
  54.                     .append(properties.getProperty(key)).append("\n");  
  55.         }  
  56.         int length = 0;  
  57.         return (length = formatResult.length()) > 0 ?   
  58.                 formatResult.substring(0, length - 1) : "";  
  59.     }  
  60.   
  61. }  
Java代码   收藏代码
  1. package com.daniele.appdemo.util;  
  2.   
  3. public class StringUtils {  
  4.       
  5.     public static boolean isNullOrBlank(String str) {  
  6.         return str == null || str.length() == 0;  
  7.     }  
  8.       
  9.     public static boolean isNotNullOrBlank(String str) {  
  10.         return !isNullOrBlank(str);  
  11.     }  
  12.   
  13. }  

运行时,依次启动SenvProtocolServer和SenvProtocolClient类即可。

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Java中自定义协议和报文格式一般可以通过以下几个步骤来实现: 1. 定义协议格式:协议格式是指通信双方在传输数据时遵循的规则,包括消息头、消息体等。可以使用自定义的二进制格式、XML、JSON等。 2. 编写网络传输代码:Java中可以使用Socket或ServerSocket类来实现网络传输。通过这些类可以建立TCP或UDP连接,并发送和接收数据。 3. 封装数据:将要发送的数据封装成协议格式的消息,包括消息头和消息体。 4. 解析数据:接收到的数据需要按照协议格式进行解析,获取消息头和消息体中的数据。 下面是一个简单的例子,演示了如何使用Java实现自定义协议和报文格式: ```java // 定义协议格式 public class MyProtocol { private int length; // 消息长度 private byte[] content; // 消息内容 // 构造函数,用于封装数据 public MyProtocol(byte[] content) { this.length = content.length; this.content = content; } // 解析数据,返回消息内容 public byte[] getContent() { return content; } // 将消息转换成二进制格式 public byte[] toByteArray() { ByteBuffer buffer = ByteBuffer.allocate(4 + length); buffer.putInt(length); buffer.put(content); return buffer.array(); } // 将二进制格式的数据转换成消息格式 public static MyProtocol fromByteArray(byte[] bytes) { ByteBuffer buffer = ByteBuffer.wrap(bytes); int length = buffer.getInt(); byte[] content = new byte[length]; buffer.get(content); return new MyProtocol(content); } } // 发送数据 Socket socket = new Socket("127.0.0.1", 8888); OutputStream os = socket.getOutputStream(); String message = "Hello World!"; MyProtocol protocol = new MyProtocol(message.getBytes()); os.write(protocol.toByteArray()); // 接收数据 InputStream is = socket.getInputStream(); byte[] buffer = new byte[1024]; int len = is.read(buffer); MyProtocol protocol = MyProtocol.fromByteArray(buffer); String message = new String(protocol.getContent()); System.out.println("Received message: " + message); ``` 在上面的例子中,我们定义了一个简单的协议格式,包括消息长度和消息内容。使用ByteBuffer类可以方便地将消息转换成二进制格式,并且实现了从二进制数据转换成消息格式的方法。在发送数据时,我们将消息封装成协议格式后发送;在接收数据时,先读取二进制数据,然后将其转换成消息格式并解析出消息内容。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值