- 声明、脳死の人々から遠ざけてください。このブログのコアは、IF-ELSE+プレフィックスではなく、URLプロトコル処理フレームワークを介してプライベートプロトコルを定義する方法です
URIとURLの違い
URI(均一なリソース識別子)均一なリソース識別子。 URL(均一なリソースの場所)均一なリソースロケーター(または統一されたリソースロケーター); URIは比較的広い概念です。 URLはURIの一種であり、URI命名メカニズムのサブセットです。 URIは抽象的であり、リソースを見つけるためのURLの特定の使用が抽象的であると言えます。 URIは通常、物理リソースパスではなく、システム全体のマッピングされたリソース識別子を指しています。 URLは、主にさまざまなWWWクライアントプログラムやサーバープログラムで使用される情報リソースを説明するためにインターネット上で使用される文字列です。 URLを使用すると、ユニファイドフォーマットを使用して、ファイル、サーバーアドレス、ディレクトリなど、さまざまな情報リソースを記述できます。
1。最初に序文をしましょう
HTTPに慣れています
url url = new url(http://www.apptest.com:8080/test/ios.php);
私たちもそれに慣れなければなりません
もちろん、URLにも慣れる必要があります。
"https"、 "ftp"、 "mailto"、 "telnet"、 "file"、 "ldap"、 "gopher"、 "jdbc"、 "rmi"、 "jndi"、 "jar"、 "doc"、 "netdoc"、 "nfs"、 "verbatim"、 ""、 "daytime"、 "systemresourc
url url = new url( "oschina://www.apptest.com:8080/test/ios.php");
あなたがそれに慣れていない場合、次の例外が常に発生します
java.net.malformedurlexception:不明なプロトコル
AndroidブラウザでAJAXを使用する場合、未定義のプロトコルはサポートされません。
2。カスタムプロトコルの理解
プロトコル:プログラミングの世界では、プロトコル自体は入力/ouput制約ルールのセットです。したがって、正確なプロトコルはI/Oを中心に展開する必要があるため、ここのプロトコルはI/Oプロトコルと呼ばれます。
契約イニシエーター:リクエスト
プロトコルレスポンダー:応答
契約の確立条件は次のとおりです。リクエストと応答は、同じ一連の契約を認識し、契約の制約に従って通信します。
3.カスタムプロトコルとURLの関係
Javaでは、カスタムプロトコルにはURLが必要ですか?
答えはノーです。
実際、I/Oの周りでは、私たちのルールの定義は完全に私たち自身の手にあります。それは、URLを離れた後に地球が向きを変えないとは言っておらず、Javaは破壊されます。
URLクラスを使用してプロトコルをカスタマイズするのはなぜですか?
答えは、URLが成熟したプロトコル通信処理フレームワークであるためです。
ここで説明したカスタムURLプロトコルは、基本的に既存のルールを介してプロトコルを拡大することに関するものです。
4。URLカスタムプライベートプロトコルプラクティス
カスタムプロトコルには応答と要求が必要であり、両当事者がお互いの合意を完全に理解する必要があることがわかっています。ここで便利にするために、HTTPプロトコルサーバーを応答として使用します。
ここでは、NGNIXサーバー + PHP + FastCGIを使用してreponseを作成します。展開コードは次のとおりです。
1。応答を定義します
<?php $ raw_post_data = file_get_contents( 'php:// input'、 'r'); echo "-------/$ _ post -----------------/n <br/>"; Echo var_dump($ _ post)。 "/n"; ECHO "------- PHP://入力-------------/n <br/>"; echo $ raw_post_data。 "/n <br/>"; $ rs = json_encode($ _ server); file_put_contents( 'text.html'、$ rs); echo '写入成功';
2。リクエストを定義します
2.1主にプロトコルプロセッサの生成に使用されるURLSTREAMHANDLERFACTORY FACTORYの実装
public class echourlstreamhandlerfactoryは、urlstreamhandlerfactory {public urlstreamhandler createurlstreamhandler(string protocol){//ここでの転用を通じて異なるスキーマ要求をカスタマイズします。もちろん、脳死者はこれがコアコードだと考えています。 URLはプロトコル処理フレームワークです。 if-elseがコアである場合、Oracleは破産しますif(protocol.equals( "echo")|| protocol.equals( "oschina")){return new echourlstreamhandler(); //プロトコル処理ハンドラーをインスタンス化します} nullを返します。 }}2.2 urlstreamhandlerの実装主な機能は、プロトコルの対応するコネクタを生成することです
public class echourlStreamhandlerはurlstreamhandlerを拡張します{@overrideprotected urlconnection openconnection(url u)throws ioexception {return new echourlconnection(u); //ここで対応する転換を実行することもできます}} 2.3プロトコル通信ルールのカスタマイズであるURLConnectionを実装します。ここでは、HTTPプロトコルを通信ルールとして使用します。ここでは、HTTPプロトコル要求を模倣します
(以下はコアコードです。ここで借用したHTTPプロトコル。もちろん、脳をかぶった人々が私に認めるように頼むIF-ELSE+URLプレフィックスの代わりに、WebSocket、SMTP、およびFTPを使用してさまざまなプロトコルと対話できます)
public class echourlconnectionはurlconnection {private socket connection = null; public final static int default_port = 80; public echourlconnection(url url){super(url);} public synchronized getInputStream()throws ioException {if(!connected) outputStream getOutputStream()throws ioException {if(!connection){connect();} return connection.getOutputStream();} public string getContentType(){return "text/plain";} public synchronized void connect()throws ioException {if(! 65535)port = default_port; this.connection = new Socket(url.gethost()、port); // trueはソケットのバッファリングをオフにしてすぐに送信することを意味します。デフォルト値はfalseです。 this.Connection.setReuseAddress(true); //デフォルト値は0であることを意味します。つまり、デフォルト値は0です。つまり、ソケット入力ストリームを介してデータを読み取るときにデータを読み取るときに、データを読み取るとき、つまり、socketimeutimetimeOutecsectionがsocketimetimetimetecseptecseptecseptecsectesを削除すると、ソケット入力ストリームを介してデータを読み取ることはありません。繰り返しますが、this.connection.setsotimeout(30000); //基礎となるソケットがすぐに閉じられるかどうかを示します//ソケットが閉じたとき、基礎となるソケットは5秒遅れ、再び閉じます。 5秒後、送信されていない残りのデータはすべて破棄されます。デフォルトでは、socket.close()メソッドが実行された場合、メソッドはすぐに返されますが、基礎となるソケットは実際にはすぐに閉じられません//残りのすべてのデータが送信されるまで一定期間遅延します//ソケットはヒントが真に閉じられ、プログラムが出力ストリームを介してデータを書き留めると、プログラムがネットワークを送信した場合のみ、プログラムが責任を負うことを意味します。プログラムはソケットを閉じます。データのバッチがネットワーク上で引き続き送信され、受信機のヒントに到達していない可能性があります。 this.connection.setsendbuffersize(1024); //データが受信されるバッファーのサイズを示します。お互いにデータを送信します)? trueはyes //そのデフォルト値はfalseです。つまり、TCPは接続が有効であるかどうかを監視せず、非アクティブなクライアントがサーバーがこれをクラッシュしたことを通知せずに永久に存在する可能性があることを意味します。 // TCPの緊急データの1バイトの送信をサポートするかどうかを示します。 Socket.SendurgentData(データ)は、1バイトのTCP緊急データを送信するために使用されます//デフォルトはfalseになります。つまり、受信者は緊急データを受信するときに処理を行い、直接廃棄します。ユーザーが緊急データを送信したい場合、trueに設定する必要があります// trueに設定した後、受信者は受信した緊急データを通常のデータと同じキューに配置します。次のコードは、高い信頼性と最小遅延伝送サービス(0x04および0x10のビットまたは操作)//ソケットクラスを使用して4つの整数を使用してサービスタイプを表します// 0x02:低コスト(バイナリは1) 0x10:最小遅延(バイナリの5番目の最後のビットは1)this.connection.settrafficclass(0x04 | 0x10); latency-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 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.get host())。append( ":")。append(url.getPort())。 2016年4月22日13:17:35 gmt/r/n "); sb.append(" vary: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 ") disconnect()throws ioexception {if(connected){this.connection.close(); this.connected = false;}}}}ここでは、プロトコル定義が完了しました。
テストコードは次のとおりです
Oschina:// localhost:8080/test/ios.phpに接続してみてください
url.seturlstreamhandlerfactory(new echourlstreamhandlerfactory()); // urlconnection.setContentHandlerFactory(new echocontenthandlerFactory()); url 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"); pw.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){//サーバーは転送チャンクエンコードを返します、/r/n0/r/n/r/nは、読み取りが終了したことを意味します。 line.length() - "/r/n0/r/n/r/n" .length()); System.out.println(line);壊す; } else {system.out.println(line); }} pw.close(); stream.close();実行結果
結果は、プロトコルが実際に正常に定義されていることを示しています
もちろん、上記のデータ分析は、エンコード情報がチャンクされているため、当社の要件を満たしていません。分析する方法要件を満たす方法、移動してください:
HTTPチャンクデータエンコードおよび解析アルゴリズム
5。その後、カスタムマイネタイプパーサー
ContentHandlerFactoryは、JavaでMinetypeを解析するために提供されます。ここで独自のパーサーを策定します。もちろん、JDKはより豊富に提供します。ここで私たちがしていることは、特別なニーズを満たすことです。
パブリッククラスECOCONTENTENTHANDLER拡張contentshandler {public object getContent(urlconnection connection)throws ioException {inputstream in = connection.getInputStream(); bufferedReader BR = new inputStreamReader(new inputStreamReader(in)); return br.readline();} public connectent() in = connection.getInputStream();使用法は非常に簡単です
urlconnection.setContentHandlerFactory(new EchocontentHandlerFactory());