Java学习笔记-网络编程
Java提供了網絡編程,并且在實際中有著大量運用
網絡編程
網絡編程概述
-
網絡模型
OSI參考模型
TCP/IP參考模型 -
網絡通訊要素
IP地址
端口號
傳輸協議
網絡參考模型
網絡通訊要素
- IP地址:InetAddress
網絡中設備的標識
不易記憶,可用主機名
本地回環地址:127.0.0.1 主機名:localhost
-
端口號
用于標識進程的邏輯地址,不同進程的標識
有效端口:065535,其中01024系統使用或保留端口 -
傳輸協議
通訊的規則
常見協議:TCP,UDP
TCP和UDP
-
UDP
將數據及源和目的封裝成數據包中,不需要建立連接
每個數據報的大小在限制在64k內
因無連接,是不可靠協議
不需要建立連接,速度快 -
TCP
建立連接,形成傳輸數據的通道
在連接中進行大數據量傳輸
通過三次握手完成連接,是可靠協議
必須建立連接,效率會稍低
Socket
- Socket就是為網絡服務提供的一種機制
- 通信的兩端都有Socket
- 網絡通信其實就是Socket間的通信
- 數據在兩個Socket間通過IO傳輸
UDP傳輸
發送端與接收端是兩個獨立的運行程序
- DatagramSocket與DatagramPacket
- 建立發送端,接收端
- 建立數據包
- 調用Socket的發送接收方法
- 關閉Socket
發送端
在發送端,要在數據包對象中明確目的地 IP 及端口
DatagramSocket ds = new DatagramSocket(); byte[] by = "hello,udp".getBytes(); DatagramPacket dp = new DatagramPacket(by, 0, by.length, InetAddress.getByName("127.0.0.1"), 10000); ds.send(dp); ds.close();接收端
在接收端,要指定監聽的端口
DatagramSocket ds = new DatagramSocket(10000); byte[] by = new byte[1024]; DatagramPacket dp = new DatagramPacket(by, by.length); ds.receive(dp); String str = new String(dp.getData(), 0, dp.getLength()); System.out.println(str + "---" + dp.getAddress()); ds.close();基于UDP的聊天程序
import java.io.*; import java.net.*; class Send implements Runnable {private DatagramSocket ds;public Send(DatagramSocket ds) {this.ds = ds;}public void run() {try {BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));String line = null;while((line = bufr.readLine()) != null) {byte[] buf = line.getBytes();DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.1.255"), 10002);ds.send(dp);if("886".equals(line))break;}} catch (Exception e) {throw new RuntimeException("發送端失敗");}} }class Rece implements Runnable {private DatagramSocket ds;public Rece(DatagramSocket ds) {this.ds = ds;}public void run() {try {while(true) {byte[] buf = new byte[1024];DatagramPacket dp = new DatagramPacket(buf, buf.length);ds.receive(dp);String ip = dp.getAddress().getHostAddress();String data = new String(dp.getData(), 0, dp.getLength());if("886".equals(data)) {System.out.println(ip + "...離開聊天室");break;}System.out.println(ip + ":" + data);}} catch (Exception e) {throw new RuntimeException("接收端失敗");}} }class Test {public static void main(String[] args) throws Exception {DatagramSocket sendSocket = new DatagramSocket();DatagramSocket receSocket = new DatagramSocket(10002);new Thread(new Send(sendSocket)).start();new Thread(new Rece(receSocket)).start();} }TCP傳輸
- Socket和ServerSocket
- 建立客戶端和服務器端
- 建立連接后,通過Socket中的IO流進行數 據的傳輸
- 關閉socket同樣,客戶端與服務器端是兩個獨立的應用程序
基本思路(客戶端)
- 客戶端需要明確服務器的ip地址以及端口,這樣才可以去試著建立連接,如果連接失敗,會出現異常
- 連接成功,說明客戶端與服務端建立了通道,那么通過IO流就可以進行數據的傳輸,而Socket對象已經提供了輸入流和輸出流對象,通過getInputStream(),getOutputStream()獲取即可
- 與服務端通訊結束后,關閉Socket
客戶端
通過Socket建立對象并指定要連接的服務端主機以及端口
Socket s = new Socket(“192.168.1.1”, 9999); OutputStream out = s.getOutputStream(); out.write("hello".getBytes()); s.close();基本思路(服務端)
- 服務端需要明確它要處理的數據是從哪個端口進入的
- 當有客戶端訪問時,要明確是哪個客戶端,可通過accept()獲取已連接的客戶端對象,并通過該對象與客戶端通過IO流進行數據傳輸
- 當該客戶端訪問結束,關閉該客戶端
服務端
建立服務端需要監聽一個端口
ServerSocket ss = new ServerSocket(9999); Socket s = ss.accept (); InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int num = in.read(buf); String str = new String(buf,0,num); System.out.println(s.getInetAddress().toString() + ":" + str); s.close(); ss.close();基于TCP的發送返回示例
import java.net.*; import java.io.*;class TcpClient {public static void main(String[] args) throws IOException {Socket s = new Socket("192.168.1.2",10004);OutputStream out = s.getOutputStream();out.write("Client Test".getBytes());InputStream in = s.getInputStream();byte[] buf = new byte[1024];int len = in.read();System.out.printf(new String(buf,0,len));s.close();} }class TcpServer {public static void main(String[] args) throws IOException {ServerSocket ss = new ServerSocket(10004);Socket s = ss.accept();String ip = s.getInetAddress().getHostAddress();System.out.printf(ip + "···connected");InputStream in = s.getInputStream();byte[] buf = new byte[1024];int len = in.read(buf);System.out.printf(new String(buf, 0 ,len));OutputStream out = s.getOutputStream();out.write("Server Get MSG".getBytes());s.close();ss.close();} }Tcp傳輸最容易出現的問題
- 客戶端連接上服務端,兩端都在等待,沒有任何數據傳輸
- 通過例程分析:
因為read方法或者readLine方法是阻塞式 - 解決辦法:
自定義結束標記
使用shutdownInput,shutdownOutput方法
TCP的并發
當A客戶端連接上以后。被服務端獲取到。服務端執行具體流程,這時B客戶端連接,只有等待
因為服務端還沒有處理完A客戶端的請求,還有循環回來執行下次accept方法。所以暫時獲取不到B客戶端對象
那么為了可以讓多個客戶端同時并發訪問服務端,服務端最好就是將每個客戶端封裝到一個單獨的線程中,這樣,就可以同時處理多個客戶端請求
示例:并發上傳文件
URI
Uniform Resource Identifies(統一資源定位符)
import java.net.*; class Test {public static void main(String[] args) throws MalformedURLException {URL url = new URL("http://192.168.1.2/web/index.html?name=cj&age=20");System.out.println("getProtocol() :" + url.getProtocol());System.out.println("getHost() :" + url.getHost());System.out.println("getPort() :" + url.getPort());System.out.println("getPath() :" + url.getPath());System.out.println("getFile() :" + url.getFile());System.out.println("getQuery() :" + url.getQuery());URLConnection conn = url.openConnection();System.out.println(conn);InputStream in = conn.getInputStream();byte[] buf = new byte[1024];int len = in.read(buf);System.out.println(new String(buf, 0, len));} }轉載于:https://www.cnblogs.com/cj5785/p/10664831.html
總結
以上是生活随笔為你收集整理的Java学习笔记-网络编程的全部內容,希望文章能夠幫你解決所遇到的問題。