網絡編程

1. InetAddress

    JDK中提供了一個InetAdderss類,該類用於封裝一個IP地址,並提供了一系列與IP地址相關的方法,下表中列出了InetAddress類的一些常用方法。


示例:

packagecom.xupt.socket001;

importjava.io.IOException;

importjava.net.InetAddress;

publicclass SocketTest01 {

    publicstaticvoid main(String[] args) throws IOException{

         InetAddress i=InetAddress.getLocalHost();

         System.out.println("獲得主機名"+i.getHostName());

         System.out.println("獲得主機IP地址"+i.getAddress());

         System.out.println("本地主機"+i);

         System.out.println(InetAddress.getAllByName("www.baidu.com"));

    }

}

2. UDP與TCP協議

2.1 UDP協議

    UDP(User Datagram Protocol 用戶數據報協議)是無連接通信協議,即在數據傳輸時,數據的發送端和接收端不建立邏輯連接。簡單來說,當一臺計算機向另外一臺計算機發送數據時,發送端不會確認接收端是否存在,就會發出數據,同樣接收端在收到數據時,也不會向發送端反饋是否收到數據。

    由於使用UDP協議消耗資源小,通信效率高,所以通常都會用於音頻、視頻和普通數據的傳輸例如視頻會議都使用UDP協議,因爲這種情況即使偶爾丟失一兩個數據包,也不會對接收結果產生太大影響。但是在使用UDP協議傳送數據時,由於UDP的面向無連接性,不能保證數據的完整性,因此在傳輸重要數據時不建議使用UDP協議。UDP的交換過程如下圖所示。

2.2TCP協議

    TCP(Transmission Control Protocol 傳輸控制協議)協議是面向連接的通信協議,即在傳輸數據前先在發送端和接收端建立邏輯連接,然後再傳輸數據,它提供了兩臺計算機之間可靠無差錯的數據傳輸。在TCP連接中必須要明確客戶端與服務器端,由客戶端向服務端發出連接請求,每次連接的創建都需要經過“三次握手”。第一次握手,客戶端向服務器端發出連接請求,等待服務器確認,第二次握手,服務器端向客戶端回送一個響應,通知客戶端收到了連接請求,第三次握手,客戶端再次向服務器端發送確認信息,確認連接。整個交互過程如下圖所示。

    由於TCP協議的面向連接特性,它可以保證傳輸數據的安全性,所以是一個被廣泛採用的協議,例如在下載文件時,如果數據接收不完整,將會導致文件數據丟失而不能被打開,因此,下載文件時必須採用TCP協議。

3. UDP通信

 UDP程序交互的流程

    發送端

        1,創建DatagramSocket對象

        2,創建DatagramPacket對象,並封裝數據

        3,發送數據

        4,釋放流資源

    接收端

        1,創建DatagramSocket對象

        2,創建DatagramPacket對象

        3,接收數據存儲到DatagramPacket對象中

        4,獲取DatagramPacket對象的內容

         5,釋放流資源

3.1 DatagramPacket

       UDP是一種面向無連接的協議,因此,在通信時發送端和接收端不用建立連接。UDP通信的過程就像是貨運公司在兩個碼頭間發送貨物一樣。在碼頭髮送和接收貨物時都需要使用集裝箱來裝載貨物,UDP通信也是一樣,發送和接收的數據也需要使用“集裝箱”進行打包,爲此JDK中提供了一個DatagramPacket類,該類的實例對象就相當於一個集裝箱,用於封裝UDP通信中發送或者接收的數據。想要創建一個DatagramPacket對象,首先需要了解一下它的構造方法。在創建發送端和接收端的DatagramPacket對象時,使用的構造方法有所不同,接收端的構造方法只需要接收一個字節數組來存放接收到的數據,而發送端的構造方法不但要接收存放了發送數據的字節數組,還需要指定發送端IP地址和端口號。

DatagramPacket的構造方法:

    使用該構造方法在創建DatagramPacket對象時,指定了封裝數據的字節數組和數據的大小,沒有指定IP地址和端口號。這樣的對象只能用於接收端,不能用於發送端。因爲發送端一定要明確指出數據的目的地(ip地址和端口號),而接收端不需要明確知道數據的來源,只需要接收到數據即可。

    使用該構造方法在創建DatagramPacket對象時,不僅指定了封裝數據的字節數組和數據的大小,還指定了數據包的目標IP地址(addr)和端口號(port)。該對象通常用於發送端,因爲在發送數據時必須指定接收端的IP地址和端口號,就好像發送貨物的集裝箱上面必須標明接收人的地址一樣。

DatagramPacket類中的常用方法:

3.2DatagramSocket

    DatagramPacket數據包的作用就如同是“快遞盒子”,可以將發送端或者接收端的數據封裝起來。然而運輸貨物只有“快遞盒子”是不夠的,還需要有集裝箱。在程序中需要實現通信只有DatagramPacket數據包也同樣不行,爲此JDK中提供的一個DatagramSocket類。DatagramSocket類的作用就類似於集裝箱,使用這個類的實例對象就可以發送和接收DatagramPacket數據包。

DatagramSocket類中常用的構造方法:


    該構造方法用於創建發送端的DatagramSocket對象,在創建DatagramSocket對象時,並沒有指定端口號,此時,系統會分配一個沒有被其它網絡程序所使用的端口號。


    該構造方法既可用於創建接收端的DatagramSocket對象,又可以創建發送端的DatagramSocket對象,在創建接收端的DatagramSocket對象時,必須要指定一個端口號,這樣就可以監聽指定的端口。

DatagramSocket類中的常用方法:


3.3UDP網絡程序

    UDP通信需要創建一個發送端程序和一個接收端程序,在通信時只有接收端程序先運行,才能避免因發送端發送的數據無法接收,而造成數據丟失。因此,首先需要來完成接收端程序的編寫。

UDP完成數據的發送:

    1,創建DatagramSocket對象

    2,創建DatagramPacket對象,並封裝數據

    3,發送數據

    4,釋放流資源

package com.xupt.socket001;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;

public class SendSocket {
	public static void main(String[] args) throws IOException {
		//創建DatagramSocket對象
		DatagramSocket ds=new DatagramSocket();
		//封裝數據
		byte[] b="像我這樣優秀的人,本該燦爛過一生,怎麼二十多年到頭來,還在人海里浮沉".getBytes();
		//創建DatagraamPacket對象
		//public DatagramPacket(byte[] buf, int length, InetAddress address,  int port)
		DatagramPacket dp=new DatagramPacket(b,b.length,InetAddress.getByName("169.254.124.173"),6666);
		//發送數據
		ds.send(dp);
		//釋放資源
		ds.close();
		
	}
}

l  UDP完成數據的接收

 UDP接收端

    1,創建DatagramSocket對象

    2,創建DatagramPacket對象

    3,接收數據存儲到DatagramPacket對象中

    4,獲取DatagramPacket對象的內容

    5,釋放流資源

package com.xupt.socket001;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class ReciveSocket {
	public static void main(String[] args) throws IOException {
		//創建DatagramSocket對象
		DatagramSocket ds=new DatagramSocket(6666);
		//創建DatagramPacket對象 
		byte[] b=new byte[1024];
		DatagramPacket dp=new DatagramPacket(b,1024);
		//接收數據
		ds.receive(dp);
		//解析數據
		InetAddress add=dp.getAddress();
		String ip=add.getHostAddress();
		byte[] data=dp.getData();
		int length=dp.getLength();
		System.out.println("IP地址:"+ip+new String(data,0,length));
	}
}

4. TCP通信

    TCP通信同UDP通信一樣,都能實現兩臺計算機之間的通信,通信的兩端都需要創建socket對象。區別在於,UDP中只有發送端和接收端,不區分客戶端與服務器端,計算機之間可以任意地發送數據。而TCP通信是嚴格區分客戶端與服務器端的,在通信時,必須先由客戶端去連接服務器端才能實現通信,服務器端不可以主動連接客戶端,並且服務器端程序需要事先啓動,等待客戶端的連接。

    在JDK中提供了兩個類用於實現TCP程序,一個是ServerSocket類,用於表示服務器端,一個是Socket類,用於表示客戶端

通信時,首先創建代表服務器端的ServerSocket對象,該對象相當於開啓一個服務,並等待客戶端的連接,然後創建代表客戶端的Socket對象向服務器端發出連接請求,服務器端響應請求,兩者建立連接開始通信。

TCP程序交互的流程

 客戶端

    1,創建客戶端的Socket對象

    2,獲取Socket的輸出流對象

    3,寫數據給服務器

    4,獲取Socket的輸入流對象

    5,使用輸入流,讀反饋信息

    6,關閉流資源

服務器端

    1,創建服務器端ServerSocket對象,指定服務器端端口號

    2,開啓服務器,等待着客戶端Socket對象的連接,如有客戶端連接,返回客戶端的Socket對象

    3,通過客戶端的Socket對象,獲取客戶端的輸入流,爲了實現獲取客戶端發來的數據

    4,通過客戶端的輸入流,獲取流中的數據

    5,通過客戶端的Socket對象,獲取客戶端的輸出流,爲了實現給客戶端反饋信息

    6,通過客戶端的輸出流,寫數據到流中

    7,關閉流資源

 

4.1 ServerSocket

    在開發TCP程序時,首先需要創建服務器端程序。JDK的java.net包中提供了一個ServerSocket類,該類的實例對象可以實現一個服務器段的程序。


使用該構造方法在創建ServerSocket對象時,就可以將其綁定到一個指定的端口號上(參數port就是端口號)。

ServerSocket的常用方法:

    ServerSocket對象負責監聽某臺計算機的某個端口號,在創建ServerSocket對象後,需要繼續調用該對象的accept()方法,接收來自客戶端的請求。當執行了accept()方法之後,服務器端程序會發生阻塞,直到客戶端發出連接請求,accept()方法纔會返回一個Scoket對象用於和客戶端實現通信,程序才能繼續向下執行。

4.2 Socket

    ServerSocket對象可以實現服務端程序,但只實現服務器端程序還不能完成通信,此時還需要一個客戶端程序與之交互,爲此JDK提供了一個Socket類,用於實現TCP客戶端程序。


    使用該構造方法在創建Socket對象時,會根據參數去連接在指定地址和端口上運行的服務器程序,其中參數host接收的是一個字符串類型的IP地址。

    該方法在使用上與第二個構造方法類似,參數address用於接收一個InetAddress類型的對象,該對象用於封裝一個IP地址。在以上Socket的構造方法中,最常用的是第一個構造方法。

Socket的常用方法:

方法聲明

功能描述

int getPort()

該方法返回一個int類型對象,該對象是Socket對象與服務器端連接的端口號

InetAddress getLocalAddress()

該方法用於獲取Socket對象綁定的本地IP地址,並將IP地址封裝成InetAddress類型的對象返回

void close()

該方法用於關閉Socket連接,結束本次通信。在關閉socket之前,應將與socket相關的所有的輸入/輸出流全部關閉,這是因爲一個良好的程序應該在執行完畢時釋放所有的資源

InputStream getInputStream()

該方法返回一個InputStream類型的輸入流對象,如果該對象是由服務器端的Socket返回,就用於讀取客戶端發送的數據,反之,用於讀取服務器端發送的數據

OutputStream getOutputStream()

該方法返回一個OutputStream類型的輸出流對象,如果該對象是由服務器端的Socket返回,就用於向客戶端發送數據,反之,用於向服務器端發送數據

    在Socket類的常用方法中,getInputStream()和getOutStream()方法分別用於獲取輸入流和輸出流。當客戶端和服務端建立連接後,數據是以IO流的形式進行交互的,從而實現通信。如下圖所示。

4.3簡單的TCP網絡程序

要實現TCP通信需要創建一個服務器端程序和一個客戶端程序,爲了保證數據傳輸的安全性,首先需要實現服務器端程序。

TCP 服務器端

 1,創建服務器ServerSocket對象(指定服務器端口號)

 2,開啓服務器了,等待客戶端的連接,當客戶端連接後,可以獲取到連接服務器的客戶端Socket對象

 3,給客戶端反饋信息

 4,關閉流資源

package com.xupt.socket002;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Serve01 {

	public static void main(String[] args) throws IOException {
		//創建ServerSocket對象
		ServerSocket ss=new ServerSocket(6666);
		//開啓服務器,等待客戶端連接
		Socket s=ss.accept();
		//讀取客戶端發送的信息
		InputStream is=s.getInputStream();
		byte[] b=new byte[1024];
		int len=0;
		while((len=is.read(b))!=-1){
			System.out.println(new String(b,0,len));
		}
		
		//在服務器端 通過客戶端輸出流給客戶端回寫數據
		OutputStream os=s.getOutputStream();
		os.write("熊貓頭 熊貓頭  我是蘑菇頭,蘑菇頭收到  over!".getBytes());
		
		//釋放資源
		s.close();
		ss.close();
		

	}

}


客戶端程序。

 TCP 客戶端

 1,創建客戶端Socket對象,(指定要連接的服務器地址與端口號)

 2,獲取服務器端的反饋回來的信息

 3,關閉流資源

package com.xupt.socket002;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class Client01 {
	public static void main(String[] args) throws IOException {
		//創建Socket對象
		Socket st=new Socket("169.254.124.173",6666);
		//通過Socket對象獲取輸出流
		OutputStream os=st.getOutputStream();
		os.write("熊貓頭 熊貓頭,我是蘑菇頭  收到請回復".getBytes());
		
		//讀取服務器端回寫的數據
		InputStream is=st.getInputStream();
		byte[] b=new byte[1024];
		int len=is.read(b);
		System.out.println(new String(b,0,len));
		
		//釋放資源
		is.close();
		st.close();
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章