java 網(wǎng)絡(luò)編程

1. 網(wǎng)絡(luò)通信概述

可以參考link中的第二點(diǎn)網(wǎng)絡(luò)基礎(chǔ)

1.1 軟件的結(jié)構(gòu)

  1. C/S 結(jié)構(gòu):客戶端、服務(wù)器

  2. B/S 結(jié)構(gòu): 瀏覽器、服務(wù)器

1.2 網(wǎng)絡(luò)通信協(xié)議

  1. 網(wǎng)絡(luò)通信協(xié)議
    一個網(wǎng)絡(luò)中的計(jì)算機(jī)需要通信,他們需要遵循一些規(guī)則
    在計(jì)算機(jī)中這些鏈接通信規(guī)則就稱之為網(wǎng)絡(luò)通信協(xié)議
    他們對數(shù)據(jù)的傳輸格式,傳輸速率,傳輸步驟等統(tǒng)一規(guī)定,通信雙方必須同時遵循這些規(guī)則才能通信

  2. TCP/IP協(xié)議

    又稱為 傳輸控制協(xié)議,因特網(wǎng)互聯(lián)協(xié)議

    定義了計(jì)算機(jī)如何介入因特網(wǎng),數(shù)據(jù)在節(jié)點(diǎn)之間傳輸?shù)臉?biāo)準(zhǔn)
    內(nèi)部包含一系列用于處理數(shù)據(jù)通信的協(xié)議,采用了4層的分層模型,每層都呼叫自己的下一層為自己提供協(xié)議完成自己的需求

鏈路層:鏈路層是用于定義物理傳輸通道,通常是對某些網(wǎng)絡(luò)連接設(shè)備的驅(qū)動協(xié)議,例如針對光纖、網(wǎng)線提供的驅(qū)動

網(wǎng)絡(luò)層:網(wǎng)絡(luò)層是整個TCP/IP協(xié)議的核心,它主要用于將傳輸?shù)臄?shù)據(jù)進(jìn)行分組,將分組數(shù)據(jù)發(fā)送到目標(biāo)計(jì)算機(jī)或者網(wǎng)絡(luò)。

運(yùn)輸層:主要使網(wǎng)絡(luò)程序進(jìn)行通信,在進(jìn)行網(wǎng)絡(luò)通信時,可以采用TCP協(xié)議,也可以采用UDP協(xié)議。

應(yīng)用層:主要負(fù)責(zé)應(yīng)用程序的協(xié)議,例如HTTP協(xié)議、FTP協(xié)議等。

1.3 協(xié)議分類

  1. UDP——無連接通信協(xié)議
    1. 發(fā)送端給接收段發(fā)送數(shù)據(jù)不需要接收端同意,也不會判斷是否存在
    2. 耗資少,通信效率高 通常用于音視頻和普通數(shù)據(jù)的傳輸 視頻會議、視頻聊天一般都采用的UDP協(xié)議
      偶爾會丟一兩個數(shù)據(jù)包,但對結(jié)果不會與太大影響。
    3. 因?yàn)閁DP的無連接性,所有我們傳輸重要數(shù)據(jù)時最好不要用UDP協(xié)議
  1. TCP——面向連接通信協(xié)議
    在傳輸數(shù)據(jù)之前會先建立連接,然后才會開始傳輸數(shù)據(jù),可以提供兩個節(jié)點(diǎn)之間無差錯的數(shù)據(jù)傳輸。
    三次握手:
    1. 客戶端向服務(wù)端發(fā)送連接請求,等待服務(wù)器確認(rèn)
    2. 服務(wù)端向客戶端發(fā)送一個響應(yīng),回應(yīng)收到了請求
    3. 客戶端再次向服務(wù)端發(fā)送已經(jīng)收到確認(rèn)信息的響應(yīng),確認(rèn)建立連接
      通過三次握手建立連接后,客戶端與服務(wù)端就可以進(jìn)行數(shù)據(jù)傳輸了。因?yàn)榇颂匦裕琓CP協(xié)議可以保證傳輸數(shù)據(jù)的安全

1.4網(wǎng)絡(luò)編程的3要素

  1. 協(xié)議
    計(jì)算機(jī)網(wǎng)絡(luò)通信必須遵循的規(guī)則,詳情見上述

  2. IP地址
    互聯(lián)網(wǎng)協(xié)議地址,設(shè)備的唯一編號
    ipV4:32位
    ipV6:128位

  3. 端口號

  • 指定了ip只能準(zhǔn)確的找到計(jì)算機(jī),但是計(jì)算機(jī)上有很多的軟件。
  • 如何準(zhǔn)確的與計(jì)算機(jī)上的軟件進(jìn)行通信呢?
  • ip:端口 就可以準(zhǔn)確的找到軟件
  • 1024之前的端口基本上被已知軟件占用
  • 端口不能多個軟件共同使用
  • 端口的范圍為 0——65535

2. TCP協(xié)議

TCP通信能實(shí)現(xiàn)兩臺計(jì)算機(jī)之間進(jìn)行數(shù)據(jù)交換,通信的兩端,嚴(yán)格的區(qū)分客戶端和服務(wù)端

TCP通信: 面向連接的通信,客戶端和服務(wù)端必須進(jìn)行三次握手才能建立邏輯連接,才能安全通信

2.1 通信的步驟:

  1. 服務(wù)器先啟動,服務(wù)器不會主動發(fā)起對客戶段的連接。
  2. 客戶端發(fā)起請求,客戶端與服務(wù)端就會建立一個邏輯連接
    連接中包括一個對象——IO對象
  3. 客戶端與服務(wù)端就可以使用
    傳輸?shù)臄?shù)據(jù)不限于字符,所以IO對象是字節(jié)流對象

2.2 服務(wù)端必須明確的事情

  1. 多個客戶端與服務(wù)端進(jìn)行交互時,服務(wù)端必須明確是哪個客戶端與其交互
    在服務(wù)端有一個方法叫,accept可以獲取到請求客戶端對象
  2. 多個客戶端與服務(wù)器進(jìn)行交互時,就需要使用多個IO流對象
    服務(wù)端是沒有IO流的,服務(wù)端可以獲取到發(fā)起請求的客戶端的Socket對象,從而使用每個客戶端中的Socket中提供的IO流與客戶端進(jìn)行交互
    • 服務(wù)器使用客戶端的字節(jié)輸入流讀取客戶端發(fā)送的數(shù)據(jù)
    • 服務(wù)器使用客戶端的字節(jié)輸出流給客戶端會寫數(shù)據(jù)
      簡單說就是服務(wù)器使用客戶端的流進(jìn)行交互
image.png

code:

  1. TcpClient服務(wù)類
public class TcpClient {
    public static void main(String[] args) throws IOException {
        //1. 創(chuàng)建一個客戶端對象Socket,構(gòu)造方法寫入IP地址和端口號
        Socket socket = new Socket("127.0.0.1",8888);

        //2. 使用Socket對象中的 方法getOutputStream();獲取到網(wǎng)絡(luò)字節(jié)輸出流
        OutputStream outputStream = socket.getOutputStream();

        //3. 使用網(wǎng)絡(luò)字節(jié)輸出流中的write方法來給服務(wù)器發(fā)送數(shù)據(jù)
        outputStream.write("你好服務(wù)器??!".getBytes());

        //拿到回復(fù)
        InputStream inputStream = socket.getInputStream();

        //讀取類容
        ReaderMsg.readers(inputStream);

        // 釋放資源
        socket.close();
    }
}
  1. TcpServer 服務(wù)類
public class TcpServer {
    public static void main(String[] args) throws IOException {
        //創(chuàng)建服務(wù)器對象ServerSocket,并通過構(gòu)造方法指定端口號
        ServerSocket serverSocket = new ServerSocket(8888);

        //使用ServerSocket中的accpet方法來得到客戶端的Socket對象
        Socket socket = serverSocket.accept();

        //使用Socket中的getInputStream();方法來獲取到網(wǎng)絡(luò)輸入流
        InputStream inputStream = socket.getInputStream();

        //讀取類容
        ReaderMsg.readers(inputStream);

        //使用Socket中的getOutputStream();方法來獲取到網(wǎng)絡(luò)輸出流
        OutputStream outputStream = socket.getOutputStream();

        outputStream.write("我收到你的問候!".getBytes());

        //關(guān)閉流
        socket.close();
        serverSocket.close();

    }
}
  1. 字符輸出類
public class ReaderMsg {
    public static void readers(InputStream inputStream) throws IOException {
        byte[] bytes = new byte[1024];
        int len = inputStream.read(bytes);
        System.out.println(new String(bytes,0,len));
    }
}

3. 綜合案例_文件上傳

客戶端:

public class TcpFileClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1",8888);
        OutputStream outputStream = socket.getOutputStream();

        BufferedInputStream biStream = new BufferedInputStream(
                new FileInputStream("I:\\download\\myeclise-2018.8.0破解文件-小笨\\readme.txt"));

        System.out.println("客戶端:我開始向服務(wù)器上傳數(shù)據(jù)");

        byte[] bytes = new byte[512];
        int lenth = 0;
        while ((lenth = biStream.read(bytes))!=-1){
            outputStream.write(bytes,0,lenth);
        }
        //不寫的話服務(wù)器將不知道什么時候才將文件上傳結(jié)束
        socket.shutdownOutput();

        InputStream inputStream = socket.getInputStream();

        lenth = 0;
        while ((lenth = inputStream.read(bytes))!=-1){
            System.out.println(new String(bytes,0,lenth));
        }

        System.out.println("客戶端:數(shù)據(jù)上傳完畢");

        biStream.close();
        socket.close();
    }
}

服務(wù)端:

public class TcpFileServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8888);

        Socket socket = serverSocket.accept();
        InputStream inputStream = socket.getInputStream();

        File file = new File("I:\\chenpengFiles\\test");
        if (!file.exists()){
            file.mkdirs();
        }

        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
                new FileOutputStream(file+"http://test.txt"));
        System.out.println("服務(wù)器:開始上傳文件");
        byte[] bytes = new byte[512];
        int lenth = 0;
        while ((lenth = inputStream.read(bytes))!=-1){
            bufferedOutputStream.write(bytes,0,lenth);
        }

        socket.getOutputStream().write("文件上傳成功!".getBytes());

        System.out.println("服務(wù)器:文件上傳成功");
        bufferedOutputStream.close();
        socket.close();
        serverSocket.close();
    }
}

優(yōu)化版:

public class TcpFileServerThread {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8888);

        while (true){
            Socket socket = serverSocket.accept();

            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        InputStream inputStream = socket.getInputStream();

                        File file = new File("I:\\chenpengFiles\\test");
                        if (!file.exists()){
                            file.mkdirs();
                        }
                        String fileName = "\\"+new Random().nextInt(99999)+".txt";
                        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
                                new FileOutputStream(file+fileName));
                        System.out.println("服務(wù)器:開始上傳文件");
                        byte[] bytes = new byte[512];
                        int lenth = 0;
                        while ((lenth = inputStream.read(bytes))!=-1){
                            bufferedOutputStream.write(bytes,0,lenth);
                        }

                        socket.getOutputStream().write("文件上傳成功!".getBytes());

                        System.out.println("服務(wù)器:文件上傳成功");
                        bufferedOutputStream.close();

                    }catch (IOException e){
                        System.out.println(e.getMessage());
                        throw new RuntimeException();
                    }finally {
                        try {
                            socket.close();
                        }catch (Exception e){
                            throw new RuntimeException();
                        }
                    }
                }
            }).start();
        }
    }
}

4. 模擬BS服務(wù)器案例

code:

public class WebServer {
    private String paths = "H:\\javaCode\\ideaCode\\java2019\\demo\\src\\com\\looc\\demo12網(wǎng)絡(luò)編程\\demo2\\";

    public void webServer() throws IOException {
        ServerSocket serverSocket = new ServerSocket(80);

        //監(jiān)聽事件
        while (true){
            //拿到socket對象
            Socket socket = serverSocket.accept();

            //開啟多線程提高效率
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        InputStream inputStream = socket.getInputStream();

                        //讀響應(yīng)體
                        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream,"US-ASCII"));

                        //讀取到文件
                        String str = br.readLine().split(" ")[1].substring(1);
                        BufferedInputStream bfs = new BufferedInputStream(
                                new FileInputStream(paths+str));

                        //回顯
                        OutputStream oStream = socket.getOutputStream();
                        oStream.write("HTTP/1.1 200 OK\r\n".getBytes());
                        oStream.write("Content-Type:text/html\r\n".getBytes());
                        oStream.write("\r\n".getBytes());

                        byte[] bytes = new byte[1024];
                        int len = 0;
                        while ((len = bfs.read(bytes))!=-1){
                            oStream.write(bytes,0,len);
                        }
                        //關(guān)閉流
                        bfs.close();
                        br.close();
                    }catch (Exception e){
                        System.out.println(e.getMessage());
                    }finally {
                        try {
                            socket.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();

        }
    }


    public static void main(String[] args) throws IOException {
        WebServer webServers = new WebServer();
        webServers.webServer();
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 計(jì)算機(jī)網(wǎng)絡(luò)概述 網(wǎng)絡(luò)編程的實(shí)質(zhì)就是兩個(或多個)設(shè)備(例如計(jì)算機(jī))之間的數(shù)據(jù)傳輸。 按照計(jì)算機(jī)網(wǎng)絡(luò)的定義,通過一定...
    蛋炒飯_By閱讀 1,367評論 0 10
  • 網(wǎng)絡(luò)編程的概述 網(wǎng)絡(luò)編程的實(shí)質(zhì)就是用來實(shí)現(xiàn)網(wǎng)絡(luò)互連的不同計(jì)算機(jī)上運(yùn)行的程序間可以進(jìn)行數(shù)據(jù)交換。 一.OSI網(wǎng)絡(luò)模型...
    思念揮霍閱讀 437評論 0 0
  • 1.網(wǎng)絡(luò)編程1.1計(jì)算機(jī)網(wǎng)絡(luò)概述網(wǎng)絡(luò)編程的實(shí)質(zhì)就是兩個(或多個)設(shè)備(例如計(jì)算機(jī))之間的數(shù)據(jù)傳輸。按照計(jì)算機(jī)網(wǎng)絡(luò)的...
    任振銘閱讀 474評論 0 1
  • 一直想成為一個精致的豬豬女孩,但總是有很多借口,阻止了我,比如說太胖,太忙,太窮。 今天休...
    若夏城雨閱讀 185評論 0 0
  • 我坐在地板上,迎面吹著風(fēng)??粗賵觯@里將是我大學(xué)三年呆的地方。 此刻,我沒有新生那股帶著對大學(xué)各種新奇的期盼,更...
    憶遺閱讀 274評論 3 0

友情鏈接更多精彩內(nèi)容