互聯網上那麼多設備,java 是如何與其餘設備通訊的呢?此次的內容是網絡通訊的基礎,有了它我們才能上網頁、玩遊戲、視頻聊天。java
Socket 客戶端套接字,用於鏈接互聯網提供服務的設備。服務器
Socket 構造方法網絡
構造方法 | 說明 |
---|---|
Socket() | 經過系統默認類型的 SocketImpl 建立未鏈接套接字 |
Socket(String host, int port) | 建立一個流套接字並將其鏈接到指定主機上的指定端口號 |
經常使用方法多線程
方法名稱 | 說明 |
---|---|
getOutputStream() | 返回此套接字的輸出流 |
getInputStream() | 返回此套接字的輸入流 |
下面示例模擬了一個 HTTP 請求app
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; import java.util.Scanner; public class TestSocket { public static void main(String[] args) { //建立套接字 try(Socket s=new Socket("www.baidu.com", 80);){ //建立向服務器發送數據的輸出流 OutputStream os=s.getOutputStream(); StringBuffer sb=new StringBuffer(); //HTTP協議 請求報文 sb.append("GET / HTTP/1.1\r\n"); sb.append("Host: www.baidu.com:80\r\n"); sb.append("Connection: Keep-Alive\r\n"); //這裏必定要一個回車換行,表示消息頭完,否則服務器會等待 sb.append("\r\n"); //發送 os.write(sb.toString().getBytes()); //獲取服務器相應內容 InputStream is=s.getInputStream(); //經過輸入流建立掃描器,並指定編碼爲utf-8防止中文亂碼 Scanner scanner=new Scanner(is,"utf-8"); while(scanner.hasNextLine()) { String line=scanner.nextLine(); System.out.println(line); } } catch (UnknownHostException e) { e.printStackTrace(); System.out.println("未知主機"); } catch (IOException e) { e.printStackTrace(); System.out.println("IO異常"); } } }
ServerSocket:實現服務器套接字,服務器套接字等待請求經過網絡傳入。它基於該請求執行某些操做,而後可能向請求者返回結果。socket
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner; public class TestServerSocket { public static void main(String[] args) { //建立 ServerSocket 監聽1666端口 try(ServerSocket server=new ServerSocket(1666)){ //阻塞方法,當有客戶端連入,獲取客戶端Socket try(Socket client=server.accept()){ //獲取客戶端發送的數據 InputStream is=client.getInputStream(); //獲取向客戶端發送數據的流 OutputStream os=client.getOutputStream(); //經過輸入流建立掃描器 try(Scanner scanner=new Scanner(is)){ PrintWriter pw=new PrintWriter(os,true/*自動刷新*/); //向客戶端發送消息 pw.println("Hello,enter bye to exit."); boolean done=false; //客戶端有輸入數據而且沒有發送 bye while(!done&&scanner.hasNextLine()) { //接收客戶端發送的數據 String line=scanner.nextLine(); //將客戶端發送的數據發回客戶端 pw.println("Echo:"+line); //若是客戶端輸入bye 結束通訊 if(line.trim().equalsIgnoreCase("bye")) {done=true;} } } } } catch (IOException e) { e.printStackTrace(); } } }
測試方式:
在DOS 中輸入命令:telnet 127.0.0.1 1666
ide
telnet 不是內部或外部命令的讀者,須要在 Windows 功能中啓用 Telnet 客戶端。測試
上面的代碼若是有多個客戶端連入就不行了,若是但願服務能被多個客戶端鏈接,可使用線程。this
多線程服務器編碼
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner; public class TestMultiServerSocket { public static void main(String[] args) { //建立 ServerSocket 監聽 1666端口 try(ServerSocket server=new ServerSocket(1666)){ while(true) { //accept() 是一個阻塞方法 Socket client=server.accept(); InputStream is=client.getInputStream(); OutputStream os=client.getOutputStream(); //開啓新的線程處理,傳入當前客戶端 Thread t=new Thread(new ThreadEchoHandler(client)); t.start(); } } catch (IOException e) { e.printStackTrace(); } } } class ThreadEchoHandler implements Runnable{ private Socket socket=null; public ThreadEchoHandler(Socket socket) { this.socket=socket; } @Override public void run() { try { InputStream is=socket.getInputStream(); OutputStream os=socket.getOutputStream(); try(Scanner scanner=new Scanner(is)){ PrintWriter pw=new PrintWriter(os,true); pw.println("Hello,enter bye to exit."); boolean done=false; while(!done&&scanner.hasNextLine()) { String line=scanner.nextLine(); pw.println("Echo:"+line); if(line.trim().equalsIgnoreCase("bye")) {done=true;} } } socket.close(); } catch (IOException e) { e.printStackTrace(); } } }
抽象類 URLConnection 是全部類的超類,它表明應用程序和 URL 之間的通訊連接。此類的實例可用於讀取和寫入此 URL 引用的資源。
Socket 能夠默認任意類型的網絡通訊,URLConnection 更適合 HTTP 請求,使用 URLConnection 進行HTTP操做更方便,模擬請求報文,獲取響應報文和內容。
URLConnection 經常使用方法
方法 | 說明 |
---|---|
connect() | 打開到此 URL 引用的資源的通訊連接(若是還沒有創建這樣的鏈接) |
getContentEncoding() | 返回 content-encoding 頭字段的值 |
getContentType() | 返回 content-type 頭字段的值 |
getHeaderFields() | 返回頭字段的不可修改的 Map |
getInputStream() | 返回今後打開的鏈接讀取的輸入流 |
setRequestProperty(String key, String value) | 設置通常請求屬性 |
獲取 URLConnection 須要先建立 URL 對象:
URL url=new URL(host);
使用 URLConnection 獲取網頁的內容
import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Scanner; public class TestURLConnection { public static void main(String[] args) { try { //建立URL對象 URL url=new URL("http://www.baidu.com"); //建立 URLConnection對象 URLConnection connection=url.openConnection(); //設置請求屬性 //connection.setRequestProperty("", ""); //鏈接 connection.connect(); //獲取輸入流 InputStream is=connection.getInputStream(); //經過輸入流構建一個掃描器 Scanner scanner=new Scanner(is,"utf-8"); while(scanner.hasNextLine()) { String line=scanner.nextLine(); System.out.println(line); } System.out.println("===響應頭==="); Map<String,List<String>> headers=connection.getHeaderFields(); for (Entry<String, List<String>> entry: headers.entrySet()) { String key=entry.getKey(); System.out.print(key+":"); for (String string : entry.getValue()) { System.out.print(string); } System.out.println(); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }