天天看點

Java基礎知識點總結--從細節再看Java(十三) --網絡程式設計一、InetAddress類二、使用UDP協定發送接收資料三、使用TCP協定發送接收資料

多數情況下,我們的程式是需要同外界通信的,Java中如果我們想要讓程式去進行通信,就要用到java.net包下的幾個類。在說這幾個類之前,我們先大體了解幾組概念。

通信有三要素,分别是IP,端口以及通信協定。

IP位址 ,可以認為是每台主機的位址,通過這個位址我們就可以找到要通信的主機在哪了。端口号也就是程序的位址,隻找到主機我們還是不能通信,我們還需要找到要通信的程序。當主機跟程序都找到之後,我們還需要有一定的傳輸資料的規範,那麼這個規範就是我們所說的傳輸協定了。我們主要用到的傳輸協定有兩種:UDP協定和TCP協定。

UDP:對資料封裝,打包,不需建立連接配接;直接把資料扔過去,每個資料報限制大小在64K,不可靠協定,但速度快。

TCP:先建立連接配接,形成傳輸資料的通道,通過三次握手完成連接配接之後才能傳輸資料,是可靠協定,效率低。分為用戶端和服務端0

一、InetAddress類

此類表示網際網路協定 (IP) 位址。有兩個子類Inet4Address,Inet6Address,分别代表兩種IP位址的結構。IP協定使用的IP 位址是32 位或 128 位無符号數字,它是一種低級協定,UDP 和 TCP 協定都是在它的基礎上建構的。

InetAddress沒有構造方法,是以我們要通過靜态方法來擷取該類的對象,這裡使用的方法是:

static InetAddress getByName(String host)  在給定主機名或Ip的情況下确定主機的 IP 位址。其中host參數可以是本地主機的名字,可以是一個IP位址,也可以是個域名。還有一種擷取本地主機Ip的方式,使用 static InetAddress getLocalHost() 。

該類還有幾個常用的方法:

String getHostAddress() : 傳回 IP 位址字元串(以文本表現形式)。 

String getHostName() : 擷取此 IP 位址的主機名。 

static InetAddress getLocalHost(): 傳回本地主機,可以用來建立本地主機的InetAddress對象。 

private static void method() throws UnknownHostException {
		//傳本地主機名參數
		InetAddress address = InetAddress.getByName("七寶");
		System.out.println(address);
		//output: 七寶/172.17.31.30
		System.out.println(address.getHostAddress());
		System.out.println(address.getHostName());
		//output:172.17.31.30
		//	 七寶
		
		//傳一個IP參數
		InetAddress address2 = InetAddress.getByName("172.17.31.30");
		System.out.println(address2);
		//output: /172.17.31.30
		System.out.println(address2.getHostAddress());
		System.out.println(address2.getHostName());
		//output:172.17.31.30
		//	 172.17.31.30
		
		//獲得本地主機名
		InetAddress address3 = InetAddress.getLocalHost();
		System.out.println(address3);
		//output:七寶/172.17.31.30
		System.out.println(address3.getHostAddress());
		System.out.println(address3.getHostName());
		//output:172.17.31.30
		//	 七寶
		
		//傳一個域名參數
		InetAddress address4 = InetAddress.getByName("www.cn.bing.com");
		System.out.println(address4);
		//output:www.cn.bing.com/204.79.197.200
		System.out.println(address4.getHostAddress());
		System.out.println(address4.getHostName());
		//output:204.79.197.200
		//	 www.cn.bing.com
		
		//傳bing的IP作參數
		InetAddress address5 = InetAddress.getByName("204.79.197.200");
		System.out.println(address5);
		//output:/204.79.197.200
		System.out.println(address5.getHostAddress());
		System.out.println(address5.getHostName());
		//output:204.79.197.200
		//	 a-0001.a-msedge.net
		
	}
           

二、使用UDP協定發送接收資料

利用Socket開發網絡程式設計已成為主流,不論是使用UDP還是TCP,我們都将用到Socket。在使用UDP傳輸資料時,我們需要對資料進行封裝,打包。需要用到DatagramSocket類和DatagramPacket類。

java.net.DatagramSocket:此類表示用來發送和接收資料報包的套接字,基于UDP協定。

          DatagramSocket() :建立Socket對象并随機配置設定端口号,用于發送端。

          DatagramSocket(int port):建立Socket對象并指定端口号port,用于接收端。

java.net.DatagramPacket:此類表示資料報包,資料包大小需要小于64K。

DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port) :構造資料報包,用來将buf數組中從offset開始,長度為 length 的内容打包發送到指定主機上的指定端口号。

DatagramPacket(byte[] buf, int length):構造 DatagramPacket,用來接收長度為 length 的資料包。

使用UPD協定發送資料的步驟

          1. 建立發送端Socket對象

          2. 建立資料并打包

          3. 發送資料包

          4. 釋放資源

用到的方法:

除構造方法外,使用DatagramSocket類中的void send(DatagramPacket p) :從此套接字發送資料報包。 

public class SendByUDP {
	public static void main(String[] args) throws IOException {
		// 建立Socket對象
		DatagramSocket ds = new DatagramSocket();

		/* 建立資料并打包 */
		// 建立資料
		String s ="hello upd~~~~~~~~~~~~~~";
		byte[] bys = s.getBytes();
		int length = bys.length;
		InetAddress address = InetAddress.getByName("七寶");
		int port = 8888;

		// 建立資料包
		DatagramPacket p = new DatagramPacket(bys,0,length,address,port);

		// 發送資料
		ds.send(p);

		// 釋放資源
		ds.close();
	}
}
           

使用UPD協定接收資料的步驟

          1. 建立接收端Socket對象

          2. 接收資料

          3. 解析資料

          4. 處理資料

          5. 釋放資源

用到的方法:

DatagramSocket類中的void receive(DatagramPacket p)接收資料

           InetAddress getAddress() :擷取發送端的IP對象 

           byte[] getData() :擷取接收到的資料,也可直接使用建立包對象時的數組

           int getLength() :擷取接收到的資料的長度。       

public class ReceiveByUDP {

	public static void main(String[] args) throws IOException {
		// 建立接收端Socket對象,需要指定端口
		DatagramSocket ds = new DatagramSocket(8888);

		// 建立接收資料報包
		byte[] buf = new byte[1024];
		DatagramPacket dp = new DatagramPacket(buf, buf.length);
		
		//接收資料
		ds.receive(dp);//阻塞
		
		// 解析資料
		InetAddress address = dp.getAddress();
		byte[] data = dp.getData();
		int length = dp.getLength();
		
		// 處理資料,可以用資料段的getData方法擷取的
		System.out.println("sender:"+ address.getHostAddress()+"---->"+ new String(data,0,length));
		// 也可以用接收資料時,資料包中存放的數組
		System.out.println("sender:"+ address.getHostAddress()+"---->"+ new String(buf,0,length));
		
		// 釋放資源
		ds.close();
	}

}
           

三、使用TCP協定發送接收資料

與UDP不同,我們在使用TCP進行通信時,用到的套接字是Socket和ServerSocket

java.net.Socket:此類實作用戶端(發送端)套接字。套接字是兩台機器間通信的端點。

java.net.ServerSocket:此類實作伺服器(接收端)套接字。伺服器套接字等待請求通過網絡傳入。

用戶端發送資料給服務端的步驟

1. 建立用戶端Socket對象(建立連接配接,需要指明Ip和port端口号)

           2. 基于Socket建立輸出流對象(發送資料的管道)

           3. 發送資料(以位元組的形式發送)

           4. 釋放資源

用到的幾個方法:

構造函數 Socket(InetAddress address, int port) :建立一個流套接字并将其連接配接到指定 IP 位址的指定端口号

Socket類中擷取輸出流的方法 OutputStream getOutputStream() :傳回此套接字的輸出流。

輸出流 OutputStream的 write() 方法,此方法用來發送資料,即将資料寫入服務端。

public class SendByTCP {

	public static void main(String[] args) throws IOException {
		// 建立Socket對象(建立連接配接,需要Ip和port,此處是與本地進行通信)
		Socket s = new Socket(InetAddress.getByName("七寶"), 80);

		// 基于Socket建立輸出流對象(發送資料的管道)
		OutputStream os = s.getOutputStream();

		// 發送資料,注意要使用位元組流發送
		os.write("hello ,tcp. im coming.".getBytes());

		// 釋放資源
		os.close();
		s.close();
	}
}
           

非常簡短的幾行代碼,我們就可以把一個簡易用戶端要做的事情寫完了,接下來我們再來看服務端如何接收這些資料。

服務端接收來自用戶端資料的步驟

1. 建立服務端ServerSocket對象

           2. 監聽(阻塞),用戶端有連接配接時,建立連接配接

           3. 建立輸入流對象(管道)

           4. 接收資料

           5. 輸出資料

           6. 釋放資源(服務端Socket一般不用關閉)

用到的幾個方法:

構造函數ServerSocket(int port) :建立綁定到特定端口的伺服器套接字。

傳回Socket對象的ServerSocket方法 Socket accept() :監聽并接收到此套接字的連接配接。

Socket類中擷取輸入流的方法 InputStream getInputStream() :傳回此套接字的輸出流。

輸入流 InputStream的 read() 方法,此方法用來接收資料,即輸入流來讀取資料。

Socket類中的 getInetAddress()方法,此方法用來擷取發送端IP。

public class ReceiveByTCP {

	public static void main(String[] args) throws IOException {
		// 建立Socket對象,端口号要與發送端設定的一緻
		ServerSocket ss = new ServerSocket(80);
		
		// 監聽(阻塞)
		Socket s = ss.accept();
		
		// 建立輸入流對象(管道)
		InputStream is = s.getInputStream();
		
		// 接收資料,當資料量大時,我們需要用到循環
		byte[] bys = new byte[1024];
		int len;
		len = is.read(bys);
		
		// 輸出資料,調用Socket的getInetAddress方法可獲得IP對象
		InetAddress inetAddress = s.getInetAddress();
		System.out.println("sender:" + inetAddress.getHostName() + "====>");
		System.out.println(new String(bys, 0, len));
		
		// 釋放資源
		is.close();
		s.close();
	}
}
           

這樣服務端的内容我們也寫完了。測試時需要注意一點,我們要先啟動服務端的程式之後,再啟動用戶端,否則服務端不會收到資料。這就好比是谷歌伺服器沒開,但你去使用google搜東西,這當然是搜不到東西的啦。雖說現在開着,但直接搜仍沒反應Σ( ° △ °|||)︴

繼續閱讀