亚洲最大av无码国产网址_日韩少妇高清无码_久久国产精品免费一级片_色综合久久综合欧美综合网_影音先锋亚洲熟女AV网

當(dāng)前位置:首頁 > 滾動 > 正文

Java 網(wǎng)絡(luò)編程 —— 客戶端協(xié)議處理框架 環(huán)球熱點(diǎn)2023-06-03 06:50:13 | 來源:博客園 | 查看: | 評論:0

概述

Java 對客戶程序的通信過程進(jìn)行了抽象,提供了通用的協(xié)議處理框架,該框架封裝了 Socket,主要包括以下類:


(相關(guān)資料圖)

URL 類:統(tǒng)一資源定位符,表示客戶程序要訪問的遠(yuǎn)程資源URLConnection 類:表示客戶程序與遠(yuǎn)程服務(wù)器的連接,客戶程序可以從 URLConnection 獲得數(shù)據(jù)輸入流和輸出流URLStreamHandler 類:協(xié)議處理器,主要負(fù)責(zé)創(chuàng)建與協(xié)議相關(guān)的 URLConnection 對象ContentHandler 類:內(nèi)容處理器,負(fù)責(zé)解析服務(wù)器發(fā)送的數(shù)據(jù),把它轉(zhuǎn)換為相應(yīng)的 Java 對象

以上類都位于 java.net 包,除 URL 類為具體類,其余的都是抽象類,對于一種具體的協(xié)議,需要創(chuàng)建相應(yīng)的具體子類。Oracle 公司為協(xié)議處理框架提供了基于 HTTP 的實現(xiàn),它們都位于 JDK 類庫的 sun.net.www 包或者其子包

URL 類的用法

下例的 HtpClient 類利用 URL 類創(chuàng)建了一個簡單的 HTTP 客戶程序,先創(chuàng)建了一個 URL 對象,然后通過它的 openStream()方法獲得一個輸入流,接下來就從這個輸入流中讀取服務(wù)器發(fā)送的響應(yīng)結(jié)果

public class HttpClient {        public static void main(String args[]) throws IOException {        //http是協(xié)議符號        URI url = new URL("http://www.javathinker.net/hello.htm");        //接收響應(yīng)結(jié)果        InputStream in = url.openStream();        ByteArrayOutputStream buffer = new ByteArrayOutputStream();        bytel] buff = new byte[1024];        int len = -l;                while((len = in.read(buff)) != -1) {            buffer.write(buff, 0, len);        }        //把字節(jié)數(shù)組轉(zhuǎn)換為字符串        System.out.println(new String(buffer.toByteArray()));    }}

URL 類的構(gòu)造方法創(chuàng)建 URLStreamHandler 實例的流程如下:

如果在 URL 緩存已經(jīng)存在這樣的 URLStreamHandler實例,則無須再創(chuàng)建,否則繼續(xù)執(zhí)行下一步

如果程序通過 URL 類的靜態(tài) setURLStreamHandlerFactory()方法設(shè)置了 URLStreamHandlerFactory接口的具體實現(xiàn)類,那么就通過這個工廠類的 createURLStreamHandler()方法來構(gòu)造 URLStreamHandler實例,否則繼續(xù)執(zhí)行下一步

根據(jù)系統(tǒng)屬性 java.prolocol.handler.pkgs來決定 URLStreamHandler具體子類的名字,然后對其實例化,假定運(yùn)行 HttpClient 的命令為:

java -Djava.protocol.handler.pkgs=com.abc.net.www | net.javathinker.protocols HttpClient

以上命令中的 -D 選項設(shè)定系統(tǒng)屬性,會先查找并試圖實例化 com.abc.net.www.http.Handler類,如果失敗,再試圖實例化 net.javathinkerprotocols.http.Handler類,如果以上操作都失敗,那么繼續(xù)執(zhí)行下一步

試圖實例化位于 sun.net.www.prolocol包的 sun.netwww.protocol.協(xié)議名.Handler類,如果失敗,URL 構(gòu)造方法就會拋出 MalforedURLException。在本例協(xié)議名是 http,會試圖實例化 sun.net.www.protocol.http.Handler

URL 類具有以下方法:

openConnection():創(chuàng)建并返回一個 URLConnection對象,這個 openConnection()方法實際上是通過調(diào)用 URLStreamHandler類的 openConnection()方法,來創(chuàng)建 URLConnection對象openStream():返回用于讀取服務(wù)器發(fā)送數(shù)據(jù)的輸入流,該方法實際上通過調(diào)用 URLConnection類的 getInputStream()方法來獲得輸入流getContent():返回包裝了服務(wù)器發(fā)送數(shù)據(jù)的 Java 對象,該方法實際上調(diào)用 URLConnection類的 getContent)方法,而 URLConnection類的 getContent()方法又調(diào)用了 ContentHandler類的 getContent()方法URLConnection 類的用法

URLConnection 類表示客戶程序與遠(yuǎn)程服務(wù)器的連接,URLConnection 有兩個 boolean 類型的屬性以及相應(yīng)的 get 和 set 方法:

dolnput:如果取值為 true,表示允許獲得輸入流,讀取遠(yuǎn)程服務(wù)器發(fā)送的數(shù)據(jù)該屬性的默認(rèn)值為 true。程序可通過 getDolnput() 和 setDolnput() 方法來讀取和設(shè)置該屬性doOutput:如果取值為 true,表示允許獲得輸出流,向遠(yuǎn)程服務(wù)器發(fā)送數(shù)據(jù)該屬性的默認(rèn)值為 false。程序可通過 getDoOutput() 和 setDoOutput() 方法來讀取和設(shè)置該屬性

URLConnection 類提供了讀取遠(yuǎn)程服務(wù)器的響應(yīng)數(shù)據(jù)的一系列方法:

getHeaderField(String name):返回響應(yīng)頭中參數(shù) name 指定的屬性的值getContentType():返回響應(yīng)正文的類型,如果無法獲取響應(yīng)正文的類型就返回 nullgetContentLength():返回響應(yīng)正文的長度,如果無法獲取響應(yīng)正文的長度,就返回 -1getContentEncoding():返回響應(yīng)正文的編碼類型,如果無法獲取響應(yīng)正文的編碼類型,就返回 null

下例的 HtpClient 類利用 URLConnection 類來讀取服務(wù)器的響應(yīng)結(jié)果

public class HttpClient {        public static void main(String args[]) throws IOException {        URL url = new URL("http://www,javathinkernet/hello.htm");        URLConnection connection = url.openConnection();        //接收響應(yīng)結(jié)果        System.out.printIn("正文類型:" + connection.getContentType());        System.out.printIn("正文長度:" + connection.getContentLength());        //讀取響應(yīng)正文        InputStream in = connection.getInputStream();                ByteArrayOutputStream buffer = new ByteArrayOutputStream();        byte[] buff = new byte[1024];        int len = -l;                while((len = in.read(buff)) != -1) {            buffer.write(buff, 0, len);        }                //把字節(jié)數(shù)組轉(zhuǎn)換為字符串        System.out.println(new String(buffer.toByteArray()));    }}
實現(xiàn)協(xié)議處理框架

本節(jié)將為用戶自定義的 ECHO 協(xié)議實現(xiàn)處理框架,共創(chuàng)建了以下類:

EchoURLConnection 類:繼承自 URLConnection 類EchoURLStreamHandler 類:繼承自 URLStreamHandler 類EchoURLStreamHandlerFactory 類:實現(xiàn) URLStreamHandlerFactory 接口EchoContentHandler 類:繼承自 ContentHandler 類EchoContentHandlerFactory 類:實現(xiàn) ContentHandlerFactory 接口1. 創(chuàng)建 EchoURLConnection 類

EchoURLConnection 類封裝了一個 Socket,在 connect() 方法中創(chuàng)建與遠(yuǎn)程服務(wù)器連接的 Socket 對象

public class EchoURLConnection extends URLConnection {        private Socket connection = null;    public final static int DEFAULT PORT = 8000;        public EchoURLConnection(URL url) {        super(url);    }        public synchronized InputStream getInputStream() throws IOException {        if(!connected) connect();        return connection.getInputStream();    }        public synchronized OutputStream getOutputStream() 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 || port > 65535) port = DEFAULT_PORT;            this.connection = new Socket(url.getHost(), port);            this.connected = true;        }    }        public synchronized void disconnect() throws IOException {        if(connected) {            //斷開連接            this.connection.close();            this.connected = false;        }    }}
2. 創(chuàng)建 EchoURLStreamHandler 及工廠類

EchoURLStreamHandler 類的 openConnection()方法負(fù)責(zé)創(chuàng)建一個 EchoURLConnection 對象

public class EchoURLStreamHandler extends URLStreamHandler {        public int getDefaultPort() {        return 8000;    }        protected URLConnection openConnection(URL url) throws IOException {        return new EchoURLConnection(url);    }}

EchoURLStreamHandlerFactory 類的 createURLStreamHandle()方法負(fù)責(zé)構(gòu)造 EchoURLStreamHandler 實例

public class EchoURLStreamHandlerFactory implements URLStreamhandlerFactory {        public URLStreamHandler createURLStreamHandler(String protocol) {        if(protocol.equals("echo"))            return new EchoURLStreamHandler();        else            return null;    }}

在客戶程序中,可以通過以下方式設(shè)置 EchoURLStreamHandlerFactory

URL.setURLStreamHandlerFactory(new EchoURLStreamHandlerFactory());URL url=new URL("echo://localhost:8000");
3. 創(chuàng)建 EchoContentHandler 類及工廠類

URLConnection 類還提供了 getContent()方法,它有兩種重載形式:

public Object getContent();public Object getContent(Class[] classes);

第二個 getContent() 方法把服務(wù)器發(fā)送的數(shù)據(jù)優(yōu)先轉(zhuǎn)換為 classes 數(shù)組第一個元素指定的類型,如果轉(zhuǎn)換失敗,再嘗試轉(zhuǎn)換第二個元素指定的類型,以此類推

下例 HttpClient 演示處理服務(wù)器發(fā)送的數(shù)據(jù)

public class HttpClient {        public static void main(String args[]) throws IOException {        URL url = new URL("http://www,javathinker.net/hello.htm");        URlConnection connection = url.openConnection();        //接收響應(yīng)結(jié)果        InputStream in = connection.getInputStream();        Class[] types = {String.class, InputStream.class};        Object obj = connection.getContent(types);                if(obj instanceof String) {            System.out.println(obj);        } else if(obj instanceof InputStream) {            in = (InputStream) obj;            FileOutputStream file = new FileOutputStream("data");            byte[] buff = new byte[1024];            int len = -l;                        while((len = in.read(buff)) != -1) {                file.write(buff, 0 ,len);            }                        System.out.println("正文保存完畢");        } else {            System.out.println("未知的響應(yīng)正文類型");        }    }}

EchoContentHandler 類負(fù)責(zé)處理 EchoServer 服務(wù)器發(fā)送的數(shù)據(jù)

public class EchoContentHandler extends ContentHandler {        /** 讀取服務(wù)器發(fā)送的一行數(shù)據(jù),把它轉(zhuǎn)換為字符串對象 */    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;    }}

第二個 getContent() 方法依次遍歷 classes 參數(shù)中的元素,判斷元素是否為 InputSuream 類型或 String 類型,如果是,就返回相應(yīng)類型的對象,它包含了服務(wù)器發(fā)送的數(shù)據(jù)。如果 classes 參數(shù)中的元素都不是 InputStream 類型或 String 類型,就返回 null

EchoContentHandlerFactory 類的 createContentHandler() 方法負(fù)責(zé)創(chuàng)建一個EchoContentHandler 對象

public class EchoContentHandlerFactory implements ContentHandlerFactory {        public ContentHandler createContentHandler(String mimetype) {        if(mimetype.equals("text/plain")) {            return new EchoContentHandler();        } else {            return null;        }    }}

在客戶程序中,可以通過以下方式設(shè)置 EchoContentHandlerFactory

URLConnection.setContentHandlerFactory(new EchoContentHandlerFactory());URL url = new URL("echo://localhost:8000");EchoURLConnection connection = (EchoURLConnection)url.openConnection();...//讀取服務(wù)器返回的數(shù)據(jù),它被包裝為一個字符串對象String echoMsg = (String)connection.getContent();
4. 在 EchoClient 類運(yùn)用 ECHO 協(xié)議處理框架
public class EchoClient {        public static void main(String args[]) throws IOException {        //設(shè)置URLStreamHandlerFactory        URL.setURLStreamHandlerFactory(new EchoURLStreamHandlerFactory());        //設(shè)置ContentHandlerFactory        URLConnection.setContentHandlerFactory(new EchoContentHandlerFactory());                URL url = new URL("echo://localhost:8000");        EchoURLConnection connection = (EchoURlConnection) url.openConnection();        //允許獲得輸出流        connection.setDoOutput(true);        //獲得輸出流        PrintWriter pw = new PrintWriter(connection.getOutputStream(), true);        while(true) {            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));            String msg = br.readLine();            //向服務(wù)器發(fā)送消息            pw.println(msg);            //讀取服務(wù)器返回的消息            String echoMsg = (String) connection.getContent();            System.out.println(echoMsg);            if(echoMsg.equals("echo:bye")) {                //斷開連接                connection.disconnect();                break;            }        }    }}

上一篇:天天短訊!傷害動物的孩子,一定是心理變態(tài)嗎? 全球簡訊:中國首制!“魔都”號下水下一篇:

最近更新
?