Java URL Custom private network protocol _java

Source: Internet
Author: User

--statement, the brain remnants of the people away, the core of this blog is not the if-else+ prefix, but how to define the private protocol through the URL Protocol processing framework

The difference between a URI and a URL

URI (Uniform Resource Identifier) Uniform Resource Identifier, URL (Uniform Resource location) Uniform Resource Locator (or Uniform Resource Locator); URIs are a relatively broad concept, A URL is a URI, a subset of the URI naming mechanism, which can be said to be abstract, and specifically to use URLs to locate resources. The URI is not typically a physical resource path, but a mapped resource identifier throughout the system. URLs are strings used on the Internet to describe information resources, and are used primarily on various WWW client programs and server programs. URL can be used in a uniform format to describe a variety of information resources, including files, server addresses and directories.


First, a preface.

We are used to HTTP

 URL url=new url (http://www.apptest.com:8080/test/ios.php);

We have to get used to it.

Of course, we have to let the URL get used to us

 "https", "ftp", "mailto", "Telnet", "File", "LDAP", "Gopher", "jdbc", "RMI", "Jndi", "Jar", "Doc", "NetDoc", "NFS", "Verba Tim "," Finger "," daytime "," Systemresource "
 URL url=new url ("oschina://www.apptest.com:8080/test/ios.php");

If you are not accustomed to, there will always be the following exception

Java.net.MalformedURLException:unknown protocol

An undefined protocol is not supported when an Android browser uses Ajax.


Two. Understanding of the customization of the agreement

Protocol: In the programming world, the protocol itself is a set of input/ouput constraint rules, so our exact protocol should be spread around I/O, so the protocol here can be called an I/O protocol.

Agreement initiator: Request

Protocol Responder: Response

The agreement was established on the condition that request and reponse recognized the same set of protocols and communicated according to the protocol constraints.


Three. Customize the relationship between the protocol and the URL

In Java, does a custom protocol necessarily require a URL?

The answer is in the negative.

In fact, around I/o, our rule definition completely has our own grasp, and did not say leave the URL the earth does not turn, Java to destroy.

Why use a URL class to customize a protocol?

The answer is that the URL is a well-established protocol communication processing framework.

Here the custom URL protocol, in essence, is more through the existing rules to expand the Protocol.

Four. URL Custom Private Protocol combat

We know that custom protocols require response and request, and both parties need to fully understand each other's agreement. For convenience, we use the HTTP protocol server as a response.

Here we use the Ngnix server +php+fastcgi to build the reponse and deploy the code as follows

1. Define Response

<?php$raw_post_data = file_get_contents (' php://input ', ' R '); 
echo "-------\$_post------------------\n<br/>"; 
echo Var_dump ($_post). "\ n";
 echo "-------php://input-------------\n<br/>"; 
Echo $raw _post_data. "\n<br/>";
 $rs = Json_encode ($_server); File_put_contents (' text.html ', $rs); Echo ' write successfully ';

2. Define Request

2.1 Implement URLStreamHandlerFactory factory, mainly used to generate protocol processor

public class Echourlstreamhandlerfactory implements URLStreamHandlerFactory {public
URLStreamHandler Createurlstreamhandler (String protocol) {
//The different schema requests are processed by the streaming here, and of course the brain residue thinks this is the core code, the URL is a set of protocol processing framework, if IF-ELSE is the core , is Oracle going to fail  
if (Protocol.equals ("echo") | | | protocol.equals ("Oschina"))   {return 
   new Echourlstreamhandler (); Instantiate protocol processing Handler  
 } return  
null;}

2.2 Implementation of URLStreamHandler, the main role is to generate a protocol corresponding to the connector

public class Echourlstreamhandler extends URLStreamHandler {
@Overrideprotected urlconnection openconnection (URL u) throws IOException {return
new echourlconnection (U); 
Here we can also carry out the corresponding shunt}
}

2.3 Implementation URLConnection, the role is the Protocol communication rules of customization, here we use the HTTP protocol as a communication rule, here we clone HTTP protocol request

(The following is the core code, the HTTP protocol borrowed here, of course, you can interact with WEBSOCKET,SMTP,FTP protocols, not the if-else+url prefix that the brain-disabled people let me admit )

public class Echourlconnection extends URLConnection {private Socket connection = null; public final static int Default_ PORT = 80;public echourlconnection (url url) {super (URL);} Public synchronized InputStream getInputStream () throws tion {if (!connected) {connect ();} return Connection.getinputstream ();} public synchronized OutputStream Getoutputstrea M () throws IOException {if (!connected) {connect ();} return Connection.getoutputstream ();} public String getContentType () {return "Text/plain";} Public synchronized void Connect () throws IOException {if (!connected) {int port = Url.getport (); if (Port < 0 | | por
T > 65535) port = Default_port;
This.connection = new Socket (Url.gethost (), port); True to turn off the socket buffer and send the data now ...
The default value is false//if the underlying implementation of the socket does not support the Tcp_nodelay option, the SocketExceptionthis.connection.setTcpNoDelay (true) is thrown.
Indicates whether the local address this.connection.setReuseAddress (true) that the socket is bound to is allowed to be reused; Indicates the wait timeout, in milliseconds, when data is received. The default value is 0, which means that it will wait indefinitely, never time out//when data is read through the input stream of the socket, if there is no data, it waits/times outThrows the sockettimeoutexception, and the socket is still connected after the exception is thrown, and you can try to read the data again this.connection.setSoTimeout (30000); Indicates whether to close the underlying socket//immediately when executing socket.close () This is set to shut down the underlying socket after 5 seconds after the socket is closed, and 5 seconds for all unsent remaining data to be discarded///By default Executes the Socket.close () method, which returns immediately, but the underlying socket does not actually close immediately//It is delayed for a period of time until all remaining data is sent to actually close the socket and disconnect//Tips: When the program writes data through the output stream, Only indicates that the program submits a batch of data to the network The network is responsible for conveying to the receiver//tips: When the program closes the socket, it is possible that this batch of data is also transmitted over the network, has not reached the receiver//tips: Here is said "the remaining data not sent out" means that this is also transmitted on the network,
Data This.connection.setSoLinger (True, 5) not received by the receiving Party;
Indicates the size of the buffer that sent the data this.connection.setSendBufferSize (1024);
The size of the buffer that represents the receiving data this.connection.setReceiveBufferSize (1024); Indicates whether a socket that is idle for a long time (no data is transferred to each end of the connection) is automatically turned off, true to//its default value is False, indicating that TCP does not monitor the validity of the connection and that inactive clients may persist indefinitely.
Without noticing that the server has crashed this.connection.setKeepAlive (true); Indicates whether to send a byte of TCP emergency data, Socket.sendurgentdata (data) is used to send a byte of TCP emergency data//its implied false, that is, the recipient receives the emergency data without any processing, directly discard it.
If the user wishes to send the emergency data, it should be set to TRUE//set to True, and the receiving party will place the received emergency data in the same queue as the normal data this.connection.setOOBInline (true); This method is used to set the service type, and the following code requests high reliability and minimal delay transfer service (bitwise OR operation of 0x04 and 0x10)//Socket classService type//0x02 is represented by 4 integers: Low cost (the penultimate digit of the binary is 1)//0x04: High reliability (the penultimate digit of the binary is 1)//0x08: Maximum throughput (the binary's penultimate fourth is 1)//0x10: Minimum delay (binary fifth digit 1)
This.connection.setTrafficClass (0x04 | 0x10); The method is used to set the connection time, delay, and the relative importance of the bandwidth (three parameters of the method represent the 3 metrics of the network transmission data)//connectiontime--This parameter represents a minimum time connection//latency---------This parameter represents the minimal delay// Bandwidth-------This parameter represents the highest bandwidth//You can assign any integer value to these parameters, and the relative size of the integers determines the relative importance of the corresponding parameter///as set here is the most important---maximum bandwidth, followed by the minimum connection time, Finally, the minimum delay this.connection.setPerformancePreferences (2, 1, 3); this.connected = true;
StringBuilder sb = new StringBuilder (); Sb.append ("POST" + url.getpath () + "http/1.1 \ r \ n"); if (Url.getport () <0 | | url.getport () >65536) {sb.append ("Host:"). Append (Url.gethost ()). Append ("\ r \ n"); Else{sb.append ("Host:"). Append (Url.gethost ()). Append (":"). Append (Url.getport ()). Append ("\ r \ n"); Sb.append ("connection:keep-alive\r\n"); Sb.append ("Date:fri, APR 2016 13:17:35"); gmt\r\n ("Sb.append: Accept-encoding\r\n "); Sb.append (" content-type:application/x-www-form-urlencoded,charset=utf-8\r\n "); Sb.append ( "Content-length:"). Append ("name=zhangsan&password=123456". GetBytes ("UTF-8"). Length). Append ("\ r \ n"); Sb.append ("\ r \ n"); This.connection.getOutputStream (). Write (Sb.tostring (). GetBytes ("UTF-8"));} Public synchronized void Disconnect () throws IOException {if (connected) {this.connection.close (); this.connected = False
 ;}}}

Here, the protocol definition is complete.

We test the code as follows

Trying to connect oschina://localhost:8080/test/ios.php

Url.seturlstreamhandlerfactory (New Echourlstreamhandlerfactory ());
Urlconnection.setcontenthandlerfactory (New Echocontenthandlerfactory ());
URL url=new url ("oschina://localhost:8080/test/ios.php");
Echourlconnection connection= (echourlconnection) url.openconnection (); 
Connection.setdooutput (True); Connection.setdoinput (true);
PrintWriter pw = new PrintWriter (New OutputStreamWriter (Connection.getoutputstream ())); 
 Pw.write ("name=zhangsan&password=123456");p W.flush ();    
 InputStream stream = Connection.getinputstream ();  int len =-1;  
byte[] buf = new byte[256];  
while ((Len=stream.read (buf, 0, 256)) >-1 {string line = new String (buf, 0, Len); if (Line.endswith ("\r\n0\r\n\r\n") &&len<256) {//The server returns the Transfer-chunked encoding, \r\n0\r\n\r\n indicates that the read is over, chunk 
 Ed Code parsing: http://dbscx.iteye.com/blog/830644 line = line.substring (0, Line.length ()-"\r\n0\r\n\r\n". Length ());  
System.out.println (line);  
Break 
  }else{System.out.println (line); 
} pw.close (); StReam.close ();
 

Run results

The results show that the protocol does define success.


of course, such as data parsing does not meet our requirements, because it is chunked encoded information, how to resolve the requirements have, please go :

HTTP chunked data encoding and parsing algorithm

Five. Something, custom Minetype parser

ContentHandlerFactory is provided in Java to parse the Minetype, we have our own parser here, and of course, the JDK is more plentiful, and it's done just to meet special needs.

public class Echocontenthandler extends ContentHandler {public
Object getcontent (urlconnection connection) throws IOException {
InputStream in = Connection.getinputstream ();
BufferedReader br = new BufferedReader (new InputStreamReader (in));
return Br.readline ();
}
Public Object getcontent (urlconnection connection, class[] classes) 
throws IOException {InputStream in = Connection.getinputstream ();
for (int i = 0; i < classes.length i++) {
if (classes[i] = = Inputstream.class) return in;
else if (classes[i] = = String.class) return getcontent (connection);
} return null;}}

The usage is very simple

 Urlconnection.setcontenthandlerfactory (New Echocontenthandlerfactory ());

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.