-성명서, 뇌 가게 사람들을 멀리하십시오. 이 블로그의 핵심은 if-Else+ Prefix가 아니라 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", "systemresource", "Systemresource"
url url = new URL ( "oschina : //www.apptest.com : 8080/test/ios.php");
익숙하지 않으면 다음 예외가 항상 발생합니다.
java.net.malformedurlexception : 알 수없는 프로토콜
Android 브라우저에서 AJAX를 사용하는 경우 정의되지 않은 프로토콜이 지원되지 않습니다.
2. 사용자 정의 프로토콜 이해
프로토콜 : 프로그래밍 세계에서 프로토콜 자체는 입력/혈구 제약 조건 규칙 세트입니다. 따라서 정확한 프로토콜은 I/O를 중심으로해야하므로 여기서 프로토콜을 I/O 프로토콜이라고 할 수 있습니다.
계약 개시 자 : 요청
프로토콜 응답자 : 응답
계약의 설립 조건은 다음과 같습니다. 요청 및 응답은 동일한 계약 세트를 인식하고 계약 제약 조건에 따라 의사 소통합니다.
3. 사용자 정의 프로토콜과 URL의 관계
Java에서는 사용자 정의 프로토콜에 URL이 필요합니까?
대답은 아니오입니다.
사실, I/O 주변의 규칙 정의는 우리 자신의 손에 완전히 있습니다. URL을 떠난 후 지구가 돌아 가지 않을 것이며 Java는 파괴 될 것이라고 말하지는 않습니다.
URL 클래스를 사용하여 프로토콜을 사용자 정의하는 이유는 무엇입니까?
답은 URL이 성숙한 프로토콜 통신 처리 프레임 워크이기 때문입니다.
여기에 언급 된 사용자 정의 URL 프로토콜은 기본적으로 기존 규칙을 통해 프로토콜을 확장하는 것입니다.
4. URL 사용자 정의 개인 프로토콜 실습
우리는 사용자 정의 프로토콜에는 응답과 요청이 필요하며 양 당사자는 서로의 계약을 완전히 이해해야합니다. 여기에서 편의를 위해 HTTP 프로토콜 서버를 응답으로 사용합니다.
여기서는 Ngnix Server + 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 구현 주로 프로토콜 프로세서를 생성하는 데 사용됩니다.
공개 클래스 EchourlStreamHandlerFactory는 urlstreamHandlerFactory {public urlStreamHandler createUrlStreamHandler (String Protocol) {// 전환을 통해 다른 스키마 요청을 사용자 정의합니다. 물론, 뇌-데드 사람들은 이것이 핵심 코드라고 생각합니다. URL은 프로토콜 처리 프레임 워크입니다. if-else가 핵심 인 경우 Oracle은 if (proceocol.equals ( "echo") || protocol.equals ( "Oschina")) {return new EchourlStreamHandler (); // 프로토콜 처리 핸들러의 인스턴스화} return null; }}2.2 URLSTREAMHANDLER 구현 주요 기능은 프로토콜의 해당 커넥터를 생성하는 것입니다.
Public Class EchourlStreamHandler는 URLStreamHandler를 확장합니다. {@OverRideProtected URLConnection OpenConnection (url u) 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; 공개 최종 정적 int default_port = 80; url url) {super (url);} public synchronized inputstream getInputStream () wrows ioException (! connected)}} repintion. outputStream getOutputStream ()는 ioException {if (! connected) {connect ();} return connection.getOutputStream ();} public string getContentType () {return "text/plain";} public synchronized void connect () drows ioexception {if (! connected) {port <| ggepport (port <| gge); 65535) port = default_port; this.connection = new Socket (url.gethost (), port); // 소켓의 버퍼링을 끄고 즉시 데이터를 보내는 진정한 수단 .. 기본값은 허위입니다. this.connection.setReuseaddress (true); // 데이터를 수신 할 때 대기 시간 초과를 제시합니다. 밀리 초로 데이터를 수신 할 때 대기 시간을 나타냅니다. 기본값은 0입니다. 즉, 소켓 입력 스트림을 통해 데이터를 읽을 때 무한 대기 중이며 시간이 없으면 시간이 걸리면, 예외가 발생한 후에도 SockettimeOutexception은 계속 될 것입니다. 데이터를 다시 읽습니다. this.connection.setsotimeout (30000); // 기본 소켓이 즉시 닫히는 지 여부를 나타냅니다. // 소켓이 닫히면 기본 소켓이 5 초로 지연된 다음 다시 닫힙니다. 5 초 후에 전송되지 않은 나머지 데이터는 폐기됩니다. 기본적으로 Socket.close () 메소드가 실행되면 방법이 즉시 반환되지만 기본 소켓은 실제로 즉시 닫히지 않습니다. // 남은 모든 데이터가 전송 될 때까지 일정 기간 동안 지연되고 소켓이 진정으로 닫히고 연결이 끊어집니다. // 팁 : 출력 스트림을 통해 데이터를 작성할 때 네트워크에 대한 데이터의 배치를 의미합니다. 프로그램이 소켓을 닫으면 데이터 배치가 네트워크에서 여전히 전송되고 수신기에 도달하지 못했을 가능성이 있습니다. // 팁 : 여기에 언급 된 "남은 데이터"는 네트워크에서 여전히 전송되고 수신기에 의해 수신되지 않은이 데이터를 말합니다. this.connection.setSendBuffersize (1024); // 데이터가 수신되는 버퍼의 크기를 나타냅니다. 서로에게 데이터를 전송하지 않습니까)? true는 예 // 기본값이 false입니다. 즉, TCP는 연결이 유효한지 여부를 모니터링하지 않으며 서버가 충돌했다는 사실에 대한 통지없이 영구적으로 존재할 수 있음을 의미합니다. // 1 바이트의 TCP 비상 데이터 전송을 지원하는지 여부를 나타냅니다. Socket.sendurgentData (데이터)는 1 바이트의 TCP 비상 데이터를 보내는 데 사용됩니다. // 기본값은 거짓으로 거짓으로 보내는 데 사용됩니다. 사용자가 비상 데이터를 보내려면 true로 설정해야합니다. // true로 설정 한 후 수신자는 수신 된 비상 데이터를 일반 데이터와 동일한 대기열에 넣습니다. 다음 코드는 높은 신뢰성 및 최소 지연 전송 서비스 (0x04 및 0x10의 비트 또는 작동)를 요청합니다. 소켓 클래스는 4 개의 정수를 사용하여 서비스 유형을 나타냅니다. // 0x02 : 저렴한 비용 (이진의 두 번째 비트 비트는 1) // 0x04 : 높은 신뢰성 (두 이진의 두 번째 비트는 1) // 0x08 : 최대 획기적입니다. 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 :"). 부록 (url.get host ()). Append ( ":"). Append (url.getport ()). Append ( "/r/n");} sb.append ( "Connection : Keep-alive/r/n"); sb.append ( "date : fri, fri, 2016 년 4 월 22 일 13:17:35 GMT/R/N "); SB.Append ("vary : accept-encoding/r/n "); ") .Append ("name = zhangsan & password = 123456 ".getBytes ("utf-8 "). length) .append ("/r/n "); sb.append ("/r/n "); this.connection.getOutputStream (). 쓰기 (sb.tostring (). getBytes ("utf-8 ")); disternect ()는 ioexception {if (connected) {this.connection.close (); this.connected = false;}}} 던지기 여기서 프로토콜 정의가 완료되었습니다.
우리의 테스트 코드는 다음과 같습니다
Oschina : // localhost : 8080/test/ios.php에 연결하십시오
url.seturlStreamHandlerFactory (new EchourlStreamHandlerFactory ()); // urlConnection.setContenthandLerfactory (new echocontenthandLlerFactory ()); 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"); pw.flush (); inputStream 스트림 = connection.getInputStream (); int len = -1; 바이트 [] buf = 새로운 바이트 [256]; while ((len = stream.read (buf, 0, 256))> -1) {String line = new String (buf, 0, len); if (line.endswith ( "/r/n0/r/n/n/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. 나중에 사용자 정의 미네 타입 파서
ContenthandLlerFactory는 Java에서 미네 타입을 구문 분석하기 위해 제공됩니다. 우리는 여기서 우리 자신의 파서를 공식화합니다. 물론 JDK는 더 풍부하게 제공합니다. 우리가 여기서하는 일은 특별한 요구를 충족시키는 것입니다.
public class echocontenthandler는 contenthandler를 확장합니다 {public object getContent (urlconnection connection)는 ioexception {incutestream in = connection.getInputStream (); bufferedReader br = new bufferedReader (in); return br.readline (); reture public connection (urlconnection, connection, classecince). {inputStream in = connection.getInputStream (); for (int i = 0; i <classe.length; i ++) {if (classs [i] == inputStream.class) return in; elose [i] == string.class) retud getContent (connection);} return null;}}}}}}}}}}}사용법은 매우 간단합니다
urlConnection.setContenthandLerfactory (new echocontenthandLerfactory ());