JAVA從零開始學習知識整理——day11—【網絡編程】

一、網絡編程入門

1.1 軟件結構
C/S結構 :全稱爲Client/Server結構,是指客戶端和服務器結構。常見程序有QQ、迅雷等軟件。
B/S結構 :全稱爲Browser/Server結構,是指瀏覽器和服務器結構。常見瀏覽器有谷歌、火狐等。

1.2 網絡通信協議
TCP/IP協議: 傳輸控制協議/因特網互聯協議( Transmission Control Protocol/Internet Protocol),是
Internet最基本、最廣泛的協議。它定義了計算機如何連入因特網,以及數據如何在它們之間傳輸的標準。它
的內部包含一系列的用於處理數據通信的協議,並採用了4層的分層模型,每一層都呼叫它的下一層所提供的
協議來完成自己的需求。

1.3 協議分類
通信的協議還是比較複雜的, java.net 包中包含的類和接口,它們提供低層次的通信細節。我們可以直接使用這
些類和接口,來專注於網絡程序開發,而不用考慮通信的細節。
java.net 包中提供了兩種常見的網絡協議的支持:
TCP:傳輸控制協議 (Transmission Control Protocol)。TCP協議是面向連接的通信協議,即傳輸數據之前,
在發送端和接收端建立邏輯連接,然後再傳輸數據,它提供了兩臺計算機之間可靠無差錯的數據傳輸。
三次握手:TCP協議中,在發送數據的準備階段,客戶端與服務器之間的三次交互,以保證連接的可
靠。
——第一次握手,客戶端向服務器端發出連接請求,等待服務器確認。
——第二次握手,服務器端向客戶端回送一個響應,通知客戶端收到了連接請求。
——第三次握手,客戶端再次向服務器端發送確認信息,確認連接。
UDP:用戶數據報協議(User Datagram Protocol)。UDP協議是一個面向無連接的協議。傳輸數據時,不需
要建立連接,不管對方端服務是否啓動,直接將數據、數據源和目的地都封裝在數據包中,直接發送。每個
數據包的大小限制在64k以內。它是不可靠協議,因爲無連接,所以傳輸速度快,但是容易丟失數據。日常應
用中,例如視頻會議、QQ聊天等。

1.4 網絡編程三要素
協議:計算機網絡通信必須遵守的規則。
IP地址:IP地址:指互聯網協議地址(Internet Protocol Address),俗稱IP。IP地址用來給一個網絡中的計算機設備做唯一的編號。假如我們把“個人電腦”比作“一臺電話”的話,那麼“IP地址”就相當於“電話號碼”。
——IP地址分類
IPv4:是一個32位的二進制數,通常被分爲4個字節,表示成 a.b.c.d 的形式,例如 192.168.65.100 。其
中a、b、c、d都是0~255之間的十進制整數,那麼最多可以表示42億個。
IPv6:由於互聯網的蓬勃發展,IP地址的需求量愈來愈大,但是網絡地址資源有限,使得IP的分配越發緊張。
有資料顯示,全球IPv4地址在2011年2月分配完畢。
爲了擴大地址空間,擬通過IPv6重新定義地址空間,採用128位地址長度,每16個字節一組,分成8組十六進
制數,表示成 ABCD:EF01:2345:6789:ABCD:EF01:2345:6789 ,號稱可以爲全世界的每一粒沙子編上一個網
址,這樣就解決了網絡地址資源數量不夠的問題。
——特殊的IP地址
本機IP地址: 127.0.0.1 、 localhost 。
端口號
網絡的通信,本質上是兩個進程(應用程序)的通信。每臺計算機都有很多的進程,那麼在網絡通信時,如何區分這些進程呢?
如果說IP地址可以唯一標識網絡中的設備,那麼端口號就可以唯一標識設備中的進程(應用程序)了。
端口號:用兩個字節表示的整數,它的取值範圍是065535。其中,01023之間的端口號用於一些知名的網
絡服務和應用,普通的應用程序需要使用1024以上的端口號。如果端口號被另外一個服務或應用所佔用,會
導致當前程序啓動失敗。
利用 協議 + IP地址 + 端口號 三元組合,就可以標識網絡中的進程了,那麼進程間的通信就可以利用這個標識與其它進程進行交互。

二、TCP 通信程序
2.1 概述
TCP通信能實現兩臺計算機之間的數據交互,通信的兩端,要嚴格區分爲客戶端(Client)與服務端(Server)。
兩端通信時步驟:

  1. 服務端程序,需要事先啓動,等待客戶端的連接。
  2. 客戶端主動連接服務器端,連接成功才能通信。服務端不可以主動連接客戶端。
    在Java中,提供了兩個類用於實現TCP通信程序:
  3. 客戶端: java.net.Socket 類表示。創建 Socket 對象,向服務端發出連接請求,服務端響應請求,兩者建
    立連接開始通信。
  4. 服務端: java.net.ServerSocket 類表示。創建 ServerSocket 對象,相當於開啓一個服務,並等待客戶端
    的連接。
    2.2 Socket類
    Socket client = new Socket(“127.0.0.1”, 6666);
    成員方法
    public InputStream getInputStream() : 返回此套接字的輸入流。
    -如果此Scoket具有相關聯的通道,則生成的InputStream 的所有操作也關聯該通道。
    -關閉生成的InputStream也將關閉相關的Socket。
    public OutputStream getOutputStream() : 返回此套接字的輸出流。
    -如果此Scoket具有相關聯的通道,則生成的OutputStream 的所有操作也關聯該通道。
    -關閉生成的OutputStream也將關閉相關的Socket。
    public void close() :關閉此套接字。
    -一旦一個socket被關閉,它不可再使用。
    -關閉此socket也將關閉相關的InputStream和OutputStream 。
    public void shutdownOutput() : 禁用此套接字的輸出流。
    -任何先前寫出的數據將被髮送,隨後終止輸出流。
    2.3 ServerSocket
    創建:ServerSocket server = new ServerSocket(6666);
    public Socket accept() :偵聽並接受連接,返回一個新的Socket對象,用於和客戶端實現通信。該方法
    會一直阻塞直到建立連接。
    2.4 簡單的TCP網絡程序
    TCP通信分析圖解
  5. 【服務端】啓動,創建ServerSocket對象,等待連接。
    Socket client = new Socket(“127.0.0.1”, 6666);
    ServerSocket server = new ServerSocket(6666);
  6. 【客戶端】啓動,創建Socket對象,請求連接。
  7. 【服務端】接收連接,調用accept方法,並返回一個Socket對象。
  8. 【客戶端】Socket對象,獲取OutputStream,向服務端寫出數據。
  9. 【服務端】Scoket對象,獲取InputStream,讀取客戶端發送的數據。
  10. 【服務端】Socket對象,獲取OutputStream,向客戶端回寫數據。
  11. 【客戶端】Scoket對象,獲取InputStream,解析回寫數據。
  12. 【客戶端】釋放資源,斷開連接。

三、綜合案例
3.1 文件上傳案例
客戶端:

package day11.DemoXXXX;

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

public class Socket_l {
    public static void main(String[] args) throws Exception {
        //創建
        Socket socket = new Socket("127.0.0.1",8845);
        //創建輸出給服務器的流
        OutputStream os = socket.getOutputStream();
        //獲取本地文件流
        FileInputStream fis = new FileInputStream("D:\\課件\\就業班\\day07-13\\day10\\1.jpg");
        //將讀取的文件傳送到服務器
        byte[] bytes = new byte[1024*1024];
        int len =0;
        while ((len = fis.read(bytes))!=-1){
            os.write(bytes,0,len);
            os.flush();
        }
        socket.shutdownOutput();

        //獲取服務器返回的信息
        InputStream is = socket.getInputStream();
        byte[] bytes1 = new byte[1024*1024];
        int len1= 0;
        while ((len1 = is.read(bytes1))!=-1){
            System.out.println(bytes1);
        }
        //關閉客戶端
        socket.close();

    }
}

服務器端:

package day11.DemoXXXX;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;

public class SS_P {
    public static void main(String[] args) throws Exception {
        //創建服務器
        ServerSocket serverSocket = new ServerSocket(8845);

        while (true){
           new Thread(()->{
               try {

                   //獲取客戶端的方法
                   Socket accept = serverSocket.accept();
                   //獲取信息,並保存
                   InputStream is = accept.getInputStream();
                   String FileName = System.currentTimeMillis()+ new Random().nextInt(99999)+".jpg";
                   FileOutputStream fos = new FileOutputStream("D:\\課件\\就業班\\day07-13\\day11\\code\\"+FileName);
                   byte[] bytes = new byte[1024*1024];
                   int len = 0;
                   while ((len = is.read(bytes))!=-1){
                       fos.write(bytes,0,len);
                       fos.flush();
                   }

                   //給服務器傳送信息
                   OutputStream os = accept.getOutputStream();
                   os.write("謝謝數據已收到".getBytes());
                   os.flush();
                   os.close();
               } catch (IOException e) {
                   e.printStackTrace();
               }
           }).start();

           //接受客戶端傳送來的數據和保存數據的輸出流並保存

           Random rd = new Random();
           String FileName = System.currentTimeMillis()+rd.nextInt(99999)+".jpg";
           FileOutputStream fos = new FileOutputStream("D:\\課件\\就業班\\day07-13\\day11\\avi\\"+FileName);
           Socket accept = serverSocket.accept();
           InputStream is = accept.getInputStream();
           byte[] bytes = new byte[1024*1024];
           int len = 0;
           while((len = is.read(bytes))!=-1){
               fos.write(bytes,0,len);
           }

           //給客戶端傳回數據
           OutputStream os = accept.getOutputStream();
           os.write("數據已收到。".getBytes());

           //釋放資源
           fos.flush();
           fos.close();
       }
    }
}

四、模擬B/S服務
代碼實現:

		public class ServerDemo {
				public static void main(String[] args) throws IOException {
					ServerSocket server = new ServerSocket(8888);
					while(true){
					Socket socket = server.accept();
					new Thread(new Web(socket)).start();
			}
	}
					static class Web implements Runnable{
					private Socket socket;
					public Web(Socket socket){
					this.socket=socket;
				}
			public void run() {
					try{
					//轉換流,讀取瀏覽器請求第一行
					BufferedReader readWb = new
					BufferedReader(new InputStreamReader(socket.getInputStream()));
					String requst = readWb.readLine();
					//取出請求資源的路徑
					String[] strArr = requst.split(" ");
					System.out.println(Arrays.toString(strArr));
					String path = strArr[1].substring(1);
					System.out.println(path);
					FileInputStream fis = new FileInputStream(path);
					System.out.println(fis);
					byte[] bytes= new byte[1024];
					int len = 0 ;
					//向瀏覽器 回寫數據
					OutputStream out = socket.getOutputStream();
					out.write("HTTP/1.1 200 OK\r\n".getBytes());
					out.write("Content‐Type:text/html\r\n".getBytes());
					out.write("\r\n".getBytes());
					while((len = fis.read(bytes))!=‐1){
					out.write(bytes,0,len);
				}
					fis.close();
					out.close();
					readWb.close();
					socket.close();
					}catch(Exception ex){
			    		}
				 }
			 }
		}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章