精华内容
下载资源
问答
  • java自定义协议

    2020-02-26 18:02:03
    在设计 C-S 结构的应用时,我们一般需要使用一种客户端C与服务端S的通信协议。现在常用的协议有HTTP,XML-RPC,SOAP等,当然,现在XML在很多场景下都用JSON替代了,这个不赘述,有些时候,我们需要设计一些自有协议,...

        在设计 C-S 结构的应用时,我们一般需要使用一种客户端C与服务端S的通信协议。现在常用的协议有HTTP,XML-RPC,SOAP等,当然,现在XML在很多场景下都用JSON替代了,这个不赘述,有些时候,我们需要设计一些自有协议,这里咱们就说一下设计自有协议时需要注意的几个点:

    1、C-S交互

        客户端与服务器之间通过信息(数据)交换来完成具体操作,举例来说,当客户端向服务器发送一个请求来执行某个操作,服务器在执行完成后向客户端回复一个处理结果,这是客户端与服务端的一次完整交互。

        当一台ComputerA向另一台ComputerB 通过网络发送信息,从A发出信息到B接收到信息需要花费一定的时间,这个网络传输时间称为时延。

    在定义协议时,完成某操作需要的交互次数越多,协议的效率就越低,如果时延很高,那效率低下就会更明显。HTTP协议完成一次操作时,只需要一次请求与一次响应,也就是只需要一次交互。而SMTP在完成一次邮件发送前会经过多次交互。

        我们只有在客户端需要向服务端发送大量的数据时,才考虑将协议操作拆分为多次交互。我们一般有两种选择:

    1、使用一次单独的交互来发送头信息

    2、将信息拆分为多个信息块

        如果服务器可以对头信息做一些初始化的预先校验,那在第一次交互时发送头信息是比较好的选择,如果头信息无效,即时数据被正常接收也是无效的。

        在传输大体量的数据时,如果中途网络连接断开,我们需要将所有数据从新发送,但如果我们将数据拆分为小的数据块,那么当网络连接失败时,我们只需要从新发送失败的数据块,然后就可以go on,已经发送成功的数据块就不需要重新发送。

    2、多请求与多响应的划分

        当通过相同连接发送多个请求时,我们需要划分出不同的请求,同时,客户端也需要划分开不同的响应。针对此问题,我们一般有两种选择:

    1、在请求信息的开始部分标明信息的字节长度

    2、在请求内容后添加结束标识

        HTTP使用的是第一种,在请求头中通过“Content-Length”标识请求数据的字节长度。它标识了请求头后有多少字节属于这个请求。这种方式相较第二种优点是减少结束符处理开销的同时,也不需要对原始信息中可能存在的与结束符相同的字符进行转义操作。缺点就是,我们在数据发送之前必须知道数据的长度,如果数据是动态生成的,我们需要缓存整个请求数据,在获取数据长度之后才能执行发送操作。

        使用结束符是,我们不必要知道我们发送的数据有多长,我们只需要在待发送数据的尾部加上结束符,但是我们需要对数据体中可能混淆结束符的字符进行转义。

    3、防火墙穿透

        大多数防火墙会阻止HTTP以外的协议通信,所以我们构建网络通信协议时基于HTTP组建新协议是一个比较好的办法。我们需要在HTTP请求及响应信息的内部来构建我们的协议。我们构建的协议形式可以是文本,可以是xml,也可以是二进制。但因为HTTP的特殊性,我们在组建某些协议时会有一定的额外开销。

    展开全文
  • 下面小编就为大家分享一篇Java自定义协议报文封装 添加Crc32校验的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • 怎样从网页上直接启动客户端应用程序?...面对这种情况也许你会想到ActiveX,但当你发现对方的客户们用IE浏览器的很少,而大多数用浏览器并不支持ActiveX,像这种... 这时再介绍一种方法给你,那就是JAVA自定义协议,其实

            怎样从网页上直接启动客户端应用程序?像启动 QQ、淘宝旺旺那样,从过点击网页里的超链接,就直接启动一个本地程序。面对这种情况也许你会想到ActiveX,但当你发现对方的客户们用IE浏览器的很少,而大多数用浏览器并不支持ActiveX,像这种具有不安全操作的ActiveX还得需要相关安全设置和数字签名的时候,你会放弃这种想法。
            这时再介绍一种方法给你,那就是JAVA自定义协议,其实这种技术在我们上网时经常可以遇到,如在浏览器中敲ftp://xxxxx.xxx 时,浏览器会自动跳转到ftp客户端或者windows资源浏览器中打开;再如,如果我们安装了迅雷后,点击网页中xunlei://xxx.xxx时,系统会自动启动web迅雷或迅雷软件。我们在网页中点播放音乐或电影视频之类的点播按钮时(例如mms://xxx.xx),客户端相关的播放软件就会自动触发。这显然是某种协议与系统中的应用程序存在着一些关联,而且你可能发现这种现象可以发生在任何浏览器下,这也是这种方法的过人之处。
            那我们怎么样才能自定义这种协议呢,答案是修改注册表中的信息,编写个.reg文件来更新注册表,按照如下格式编写这个.reg文件并执行。
      Windows Registry Editor Version 5.00
      [HKEY_CLASSES_ROOT\自定义协议名称]
      @="URL:自定义协议名称 Protocol"
      "URL Protocol"=""
      [HKEY_CLASSES_ROOT\自定义协议名称\DefaultIcon]
      @="应用程序路径"
      [HKEY_CLASSES_ROOT\自定义协议名称\shell]
      @=""
      [HKEY_CLASSES_ROOT\自定义协议名称\shell\open]
      @=""
      [HKEY_CLASSES_ROOT\自定义协议名称\shell\open\command]
      @="应用程序路径" \"%1\""


      例如在网页中启动一个计算器的应用程序如下:
      Windows Registry Editor Version 5.00
      [HKEY_CLASSES_ROOT\TestCalc]
      @="URL:TestCalc Protocol"
      "URL Protocol"=""
      [HKEY_CLASSES_ROOT\TestCalc\DefaultIcon]
      @="c:\\windows\\system32\\calc,1"
      [HKEY_CLASSES_ROOT\TestCalc\shell]
      @=""
      [HKEY_CLASSES_ROOT\TestCalc\shell\open]
      @=""
      [HKEY_CLASSES_ROOT\TestCalc\shell\open\command]
      @="\"c:\\windows\\system32\\calc\" \"%1\""


      执行完这个.reg文件后,在浏览器中敲入TestCalc://xxx试试,你会发现,你的目的就达到了。

    展开全文
  • java 自定义通讯协议

    千次阅读 2017-07-12 17:58:09
    JAVA默认提供了对file,ftp,gopher,http,https,jar,mailto,netdoc协议的支持。当我们要利用这些协议来创建应用时,主要会涉及到如下几个类:  1.java.net.URL:URL资源  2.java.net.URLConnection:各种URL...

     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类即可。

    展开全文
  • Java自定义URL协议

    2011-08-31 18:26:48
    协议进行扩展的能力,通过扩展用户可以自定义 URL 通信协议, JDK 默认提供了对 HTTP,FTP,JAR,FILE 等的实现,而当需要自己定义通信协议的时候,就需要利用 JDK 提供的对 URL 扩展机制进行自定义。   ...

            Java 提供了对 URL 协议进行扩展的能力,通过扩展用户可以自定义 URL 通信协议, JDK 默认提供了对 HTTP,FTP,JAR,FILE 等的实现,而当需要自己定义通信协议的时候,就需要利用 JDK 提供的对 URL 扩展机制进行自定义。

             JDK 主要提供了如下三种方式对 URL 进行扩展,每种方式都有各自的使用场景,下面我们分别看看具体 JDK 都给我们提供了哪些扩展点。

    1.         实现 URLStreamHandlerFactory 接口,然后调用 URL.setURLStreamHandlerFactory.

    采用这种方式的情况下,需要确保应用的其他地方没有调用 setURLStreamHandlerFactory ,因为此方法只能调用一次,如果多次调用会抛出 java.lang.Error: factory already defined. 比如在一些应用服务器的中使用的时候就要多加注意。

     

    2.         创建 URLStreamHandler 的子类,这种方式必须满足如下两个约定:

    a)         子类的类名必须是 Handler ,同时最后一级的包名必须是协议的名称,比如你自己定义了名为 mem 的协议,那么 handler 的全名不须是 com.company.protocol.Handler.

    b)         JVM 启动的时候,需要设置 java.protocol.handler.pkgs 系统属性,如果有多个实现类,那么中间用 | 隔开。

     

    上面两个约定我们可以通过查看 JDK 中的 URL 的源代码,可以清晰的看到为什么要遵循这两个约定。下面我们就看一下 JDK 中关于 URL 的源代码。

    static URLStreamHandler getURLStreamHandler(String protocol) {
    		  …… ……   
                
                if (handler == null) {
               	 //这里获取java.protocol.handler.pkgs系统属性,同时用“|”隔开 
                    String packagePrefixList = null;
                    packagePrefixList
                        = (String) java.security.AccessController.doPrivileged(
                        new sun.security.action.GetPropertyAction(
                            protocolPathProp, ""));
                    if (packagePrefixList != "") {
                        packagePrefixList += "|";
                    }
    
                    // REMIND: decide whether to allow the "null" class prefix
                    // or not.
                    packagePrefixList += "sun.net.www.protocol";
    			
                    
                    StringTokenizer packagePrefixIter =
                        new StringTokenizer(packagePrefixList, "|");
    
                    while (handler == null &&
                        packagePrefixIter.hasMoreTokens()) {
    
                        String packagePrefix =
                            packagePrefixIter.nextToken().trim();
                        try {
    					//这里packagePrefix就是你自己制定的包名,protocol为你自定义的协议名,这
                            String clsName = packagePrefix + "." + protocol +
                                ".Handler";
                            Class cls = null;
                            try {
                                cls = Class.forName(clsName);// 用加载URL的类加载器加载
                            } catch (ClassNotFoundException e) {
                                ClassLoader cl = ClassLoader.getSystemClassLoader(); //采用系统类加载器加载
                                if (cl != null) {
                                    cls = cl.loadClass(clsName);
                                }
                            }
                            if (cls != null) {
                                handler =
                                    (URLStreamHandler) cls.newInstance();
                            }
                        } catch (Exception e) {
                            // any number of exceptions can get thrown here
                        }
                    }
                }
            }
    }
    

    当采用这种方法的时候,需要注意的是自己写的 Handler 类必须放在系统类加载器可以加载到的地方。

     

    3   实例化一个 URL 对象的时候传递一个 URLStreamHandler 的实例。这种方式的情况下, JDK 需要一个名为 specifyStreamHandler NetPermission ,这就要求你需要去修改 jdk 安装目录下的 java.policy 文件进行授权。

    展开全文
  • 基于Java Socket的自定义协议

    千次阅读 2017-04-01 15:07:05
    上一篇文章中,我们对socket编程和自定义协议做了一个简单的了解,本文将在此基础上加以深入,来实现Android和服务器之间的长连接,现定义协议如下: 数据类协议(Data)  长度(length,32bit)版本号(version...
  • Java - Apache Mina 自定义协议通信

    千次阅读 2014-06-30 23:13:01
    一、定义协议实体 ... * 自定义协议的消息体 */ public class MyMsg { /** * 消息长度 */ private Integer lenth; /** * 发送人 */ private Long sender; /** * 接收人 */ p
  • JAVA自定义网络通信协议

    千次阅读 2013-05-11 18:51:23
     JAVA默认提供了对file,ftp,gopher,http,https,jar,mailto,netdoc协议的支持。当我们要利用这些协议来创建应用时,主要会涉及到如下几个类:  1.java.net.URL:URL资源  2.java.net.URLConnection:各种URL资源...
  • URI与URL的区别一.先来序言一段二.协议的自定义的理解三.自定义协议与URL的关系四.URL自定义私有协议实战五.后话,自定义mineType解析器
  • Java实现自定义HTTP协议

    千次阅读 2019-06-12 17:08:37
    Java实现HTTP协议 代码: package com.we; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels....
  • 除此之外,在开发过程中可以进行header的自定义。 现在进入正题,解析http报文,java代码如下 package HTTPParser ; import HTTPParser . httpMsgParser . HttpMsgParser ; import java . util . ...
  • java socket通信自定义消息协议

    热门讨论 2010-05-26 16:26:34
    java socket通信自定义消息协议,socket以字节码的方式通信传递,客户端与服务器端分别进行转换与解析的过程实现简单的消息协议
  • 如何自定义协议

    2020-12-28 08:51:41
    何为自定义协议,其实是相对标准协议来说的,这里主要针对的是应用层协议;常见的标准的应用层协议如http、ftp、smtp等,如果我们在网络通信的过程中不去使用这些标准协议,那就需要自定义协议,比如我们常用的RPC...
  • ![图片说明](https://img-ask.csdn.net/upload/202003/24/1585035030_975869.png) 以上协议头,如何用java封装?
  • 上一篇文章中,我们对socket编程和自定义协议做了一个简单的了解,本文将在此基础上加以深入,来实现Android和服务器之间的长连接,现定义协议如下
  • 【Java编程系列】Java自定义标签-Tag

    万次阅读 2017-11-13 15:54:48
    1.前言 前段时间,临时调到其他项目组帮忙,做一个页面权限控制模块。当时因为业务要求,一个用户可能会对应多个角色,所以我一...于是之后他自行提出了一种自定义标签的做法,来进行权限控制。 2.自定义标签Tag的使用
  • netty自定义协议

    2016-07-15 15:39:17
    netty实现自定义协议通信,形如: /** * socketHeader定义 40 + 4+ 100 +4 * 序列号 40bytes 不足前面补0 * 来源 4bytes * 指令 8bytes 不足前面补0 形如0001, 0000:心跳 * 长度 4bytes */ 心跳连接 运行 ...
  • 在正式给大家介绍自定义协议之前,我们先对网络传输和协议解析的相关知识点做一个基本的介绍,尽管这些知识点我们在学校里学过,但难免会有所遗忘,这里先做一个简单的介绍,以便对后文的内容理解更加顺畅。...
  • 以太网发送自定义协议数据包java

    千次阅读 2016-08-05 11:38:34
     //设置自定义协议类型  int type = Integer.decode("0x7799");  ether.frametype = (short)type;  byte[] desmac = stomac(macAddress);//目标mac地址  byte[] srcmac = null;  try {  srcmac =...
  • Java基于netty,根据自定义通讯协议,解析TCP报文(报文为C++结构体) 本文仅说明netty服务端接收自定义通讯协议的报文后,如何根据协议内容进行解析。 通讯协议 通信方式 采用socket TCP 进行通信,服务端应采用多...
  • 上一集我们介绍了如何为java-cef添加flashplayer支持。  本视频介绍java-cef中的自定义协议 本作品采用知识共享署名-非商业性使用-禁止演绎 3.0 中国大陆许可协议进行许可。...
  • Netty实现自定义协议

    千次阅读 2020-01-06 17:36:00
    关于协议,使用最为广泛的是HTTP协议,但是在一些服务交互领域,其使用则相对较少,主要原因有三方面: HTTP协议会携带诸如header和cookie等信息,其本身对字节的利用率也较低,这使得HTTP协议比较臃肿,在承载相同...
  • 自定义简单的"投票"协议 程序支持两种请求。一种是查询( inquiry),即向服务器询问给定候选人当前获得的投票总数。服务器发回一个响应消息,包含了原来的候选人 ID和该候选人当前(查询请求收到时)获得的选票...
  • RPC创建自定义协议

    2021-01-12 22:26:25
    在Netty 中要完成一个自定义协议,其实非常简单,只需要定义一个普通的Java 类即可。我们现在手写RPC 主要是完成对Java 代码的远程调用(类似于RMI,大家应该都很熟悉了吧),远程调用Java 代码哪些内容是必须由网络...
  • 下面给出一个实现了自定义构建和解析协议消息的Demo(书上例子)。  该例子是一个简单的投票协议。这里,一个客户端向服务器发送一个请求消息,消息中包含了一个候选人的ID,范围在0~1000。程序支持两种请求:一...
  • java自定义http请求

    千次阅读 2016-05-31 23:12:28
    HttpResponser.java package com.cg.scoket.httpscodket; import java.util.Vector; /** * 响应对象 */ public class HttpResponser { String urlString; int defaultPort; String file; String ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 136,079
精华内容 54,431
关键字:

java自定义协议

java 订阅