Javaday14網絡編程

day14_面向對象(網絡編程)
    一.網絡編程對象入門
        1.軟件架構介紹
            CS架構:Client/Server 客戶端/服務器
                比如:QQ,迅雷,淘寶,京東
            BS架構:Browser/Server 瀏覽器/服務器
                比如:淘寶網,京東網
            (BS慢慢會取代CS,方便)
        2.網絡通信協議介紹
            網絡通信協議:互聯網上的計算機之間進行數據交互,需要遵循的規則
            交通管理條例(類比)
        3.常用的通信協議
            TCP/IP協議
            IP協議:互聯網協議
                注意規定就是計算的IP地址相關內容
            TCP協議(傳輸控制協議):
                特點:面向有鏈接(通過三次握手建立連接)
                能保證數據的完整性和安全性,性能較低
                (應用:客戶端下載)
            UDP協議(用戶數據報協議):
                特點:面向無連接(發數據之前不需要建立連接,甚至不需要關心對象是否存在)
                不能保證數據完整性和安全性,性能很高
                (應用:視頻通話,屏幕共享)
        4.網絡編程的三要素
            a.各種網絡協議
            b.IP地址
                IP地址是每一臺聯網的計算機的唯一標識
                IPv4地址:由32位二進制組成。4個字節,一共有42億種
                    127   .   128    .    234    .    222
                一個字節的取值範圍:0~255
            c.端口號
                是一臺計算機上不同軟件的標識,一共有0~65535個端口號。我們在寫程序時,建議使用1024以上端口號
                用兩個字節表示的整數,它的取值範圍是0~65535。其中,0~1023之間的端口號用於一些知名的網絡服務和應用,普通的應用程序需要使用1024以上的端口號。如果端口號被另外一個服務或應用所佔用,會導致當前程序啓動失敗。
        擴展:
            a.IP地址的未來
                IPv4版本:32位組成,只能標識42億種IP(面臨枯竭)
                IPv6版本:128位組成,號稱可以爲全球的每一粒沙子起一個IP地址,且不重複
            b.IP地址的獲取和測試(Dos命令)
                查看本機IP命令:ipconfig(查看以太網IP地址)
                檢查網絡是否通暢:ping 對方的IP
            c.特殊的IP地址
                127.0.0.1 本機迴環地址(測試用的)
    二.TCP通信
        1.TCP通信分爲客戶端和服務器
            客戶端:個人電腦,手機
            服務器:公司大型電腦 1P =1024T 1E = 1024P
        2.TCP中的兩個重要的類
            代表客戶端:Socket(套接字)
            代表服務器:ServerSocket(服務器套接字)
        3.Socket類的介紹和使用
            a.構造方法
                public Socket(String ip, int port);此構造的底層會自動連接服務器(三次握手)
                如果連接成功,那麼該客戶端對象成功創建
                如果連接失敗,直接拋出異常
            b.常用方法
                public OutputStream getOutputStream(); 獲取通道輸出流
                public InputStream getInputStream(); 獲取通道的輸入流    
                public void shutDownOutput(); 關閉通道中的輸出流
                public void shutDownInput(); 關閉通道中的輸入流

                public void close(); 關閉客戶端對象        4.ServerSocket類的介紹和使用
            a.構造方法:
                public ServerSocket(int port); 創建服務器,並指定服務器所在的端口號
            b.常用的成員方法
                public void close(); 關閉服務器對象
                public Socket accept(); 接收連接到服務器的那個客戶端對象
        5.簡單的TCP通信實現(單向實現)***************

public class TCPClient {
    public static void main(String[] args) throws IOException {
        //1.創建客戶端對象
        Socket client = new Socket("127.0.0.1",54321);
        System.out.println("客戶端成功連接到服務器...");
        //2.獲取通道中的輸出流
        OutputStream out = client.getOutputStream();
        //3.調用out的寫數據方法
        out.write("你好服務器,我是你大爺...".getBytes());
        System.out.println("數據發送成功...");
        //4.釋放資源
        out.close();
        client.close();
        System.out.println("客戶端成功關閉...");
    }
}

public class TCPServer {
    public static void main(String[] args) throws IOException {
        //1.創建服務器對象
        ServerSocket server = new ServerSocket(54321);
        System.out.println("服務器成功啓動...");
        //2.接收客戶端對象
        System.out.println("等待客戶端的連接...");
        Socket client = server.accept();//accept方法具體阻塞功能
        System.out.println("有客戶端來了...");
        //3.獲取通道中的輸入流
        InputStream in = client.getInputStream();
        //4.調用in的讀數據方法
        byte[] bs = new byte[1024];
        int len = in.read(bs);
        System.out.println("客戶端發送消息:"+new String(bs,0,len));
        //5.釋放資源
        in.close();
        client.close();
        server.close();
        System.out.println("服務器成功關閉...");
    }
}

        6.簡單的TCP通信實現(雙向實現)
            單向通信:
                客戶端連接到服務器後,給服務器發送信息,然後關閉
                服務器獲取到客戶端連接後,讀取客戶端的信息,然後關閉
            雙向通信:
                客戶端連接到服務器後,給服務器發送信息,等待服務器回的信息,讀取後再關閉
                服務器獲取到客戶端連接後,讀取客戶端的信息,然後給客戶端回信息,再關閉

public class TCPClient {
    public static void main(String[] args) throws IOException {
        //1.創建客戶端對象
        Socket client = new Socket("127.0.0.1", 54321);
        System.out.println("客戶端成功連接到服務器...");
        //2.獲取通道中的輸出流
        OutputStream out = client.getOutputStream();
        //3.調用out的寫數據方法
        out.write("你好服務器,我是你大爺...".getBytes());
        System.out.println("數據發送成功...");
        //======雙向通信,不要立刻關閉,而要讀取服務器回的信息======
        //4.獲取通道中的輸入流
        InputStream in = client.getInputStream();
        //5.從流中讀取服務器回的信息
        byte[] bs = new byte[1024];
        int len = in.read(bs);
        System.out.println("服務器回信息:" + new String(bs, 0, len));
        //6.釋放資源
        out.close();
        client.close();
        System.out.println("客戶端成功關閉...");
    }
}

public class TCPServer {
    public static void main(String[] args) throws IOException {
        //1.創建服務器對象
        ServerSocket server = new ServerSocket(54321);
        System.out.println("服務器成功啓動...");
        //2.接收客戶端對象
        System.out.println("等待客戶端的連接...");
        Socket client = server.accept();//accept方法具體阻塞功能
        System.out.println("有客戶端來了...");
        //3.獲取通道中的輸入流
        InputStream in = client.getInputStream();
        //4.調用in的讀數據方法
        byte[] bs = new byte[1024];
        int len = in.read(bs);
        System.out.println("客戶端發送消息:"+new String(bs,0,len));
        //========雙向通信,不要立刻關閉,而要給客戶端回信息==========
        //5.獲取通道中的輸出流
        OutputStream out = client.getOutputStream();
        //6.向客戶端回信息
        out.write("您的信息已經收到,您可以安息了...".getBytes());
        System.out.println("已經成功給客戶端回信息了...");
        //=======雙向通信,不要立刻關閉,而要給客戶端回信息===========
        //7.釋放資源
        out.close();
        in.close();
        client.close();
        server.close();
        System.out.println("服務器成功關閉...");
    }
}

    三.綜合案例:文件上傳
        1.文件上傳案例分析(畫圖分析)


        

        2.文件上傳案例實現(代碼演示)

/**
 * TCP文件上傳的客戶端
 */
public class TCPFileUploadClient {
    public static void main(String[] args) throws IOException {
//        1.創建客戶端對象
        Socket client = new Socket("127.0.0.1",11111);
        System.out.println("連接服務器成功...");
//        2.獲取通道中的輸出流
        OutputStream out = client.getOutputStream();
//        3.創建文件的字節輸入流
        FileInputStream fis = new FileInputStream("1.png");
//        循環:一邊從文件中讀取對象,一邊通過輸出流發送給服務器
        System.out.println("正在發送文件....");
        byte[] bs = new byte[1024];
        int len = 0;
        while ((len = fis.read(bs))!=-1) {
            //發送服務器
            out.write(bs, 0, len);
        }
        //當客戶端文件發送完畢,一定要告知服務器
        //解決方案;把輸出流關閉
        client.shutdownOutput();
        System.out.println("發送發送完畢....");
//        4.獲取通道中的輸入流(讀取服務器的反饋信息)
        InputStream in = client.getInputStream();
        byte[] bs1 = new byte[1024];
        int len1 = in.read(bs1);
        System.out.println("服務器說:" + new String(bs1, 0, len1));
//        5.釋放資源
        in.close();
        fis.close();
        out.close();
        client.close();
        System.out.println("客戶端成功關閉...");
    }
}

public class TCPFileUploadServer {
    public static void main(String[] args) throws IOException {
//        1.創建服務器對象
        ServerSocket server = new ServerSocket(11111);
        System.out.println("服務器啓動成功...");
//        2.接收客戶端對象
        System.out.println("等待客戶端連接...");
        Socket client = server.accept();
        System.out.println("有客戶端連接了,"+client.getInetAddress().getHostAddress());
//        3.獲取通道中的輸入流
        InputStream in = client.getInputStream();
//        4.創建文件的字節輸出流
        String filename = "G:\\uploads\\1.png";
        FileOutputStream fos = new FileOutputStream(filename);
//        循環:一邊從輸入流中讀數據,一邊寫到文件中
        System.out.println("正在接收客戶端發送的文件..");
        byte[] bs = new byte[1024];
        int len = 0;
        while ((len = in.read(bs)) != -1) {
            //寫到文件中
            fos.write(bs, 0, len);
        }
        System.out.println("服務器接收文件完畢...");
//        5.獲取通道中的輸出流(向客戶端發送反饋信息)
        OutputStream out = client.getOutputStream();
        out.write(("您的文件收到了,保存到服務器:"+filename).getBytes());
        System.out.println("給客戶端發送反饋完畢...");
//        6.釋放資源
        out.close();
        fos.close();
        in.close();
        client.close();
        server.close();
        System.out.println("服務器關閉成功...");
    }
}


        3.文件中上傳案例實現的不足之處
            a.服務器保存文件時,由於文件名固定,導致只有一個文件
            b.每次啓動服務器只能服務一個客戶端
            c.如果客戶端的數據過多,導致和該客戶端的交互時間太長,無法接受下一個客戶端
        4.文件上傳案例的優化實現(代碼演示)

public class TCPFileUploadServer {
    public static void main(String[] args) throws IOException {
//        1.創建服務器對象
        ServerSocket server = new ServerSocket(11111);
        System.out.println("服務器啓動成功...");
        while (true) {
//        2.接收客戶端對象
            System.out.println("等待客戶端連接...");
            Socket client = server.accept();
            System.out.println("有客戶端連接了," + client.getInetAddress().getHostAddress());

            //創建一個線程
            new Thread(new Runnable() {
                @Override
                public void run() {
                    //任務
                    try {
                        //        3.獲取通道中的輸入流
                        InputStream in = client.getInputStream();
                        //        4.創建文件的字節輸出流
                        String filename = "G:\\uploads\\" + System.currentTimeMillis() + new Random().nextInt(100) + ".png";
                        FileOutputStream fos = new FileOutputStream(filename);
                        //        循環:一邊從輸入流中讀數據,一邊寫到文件中
                        System.out.println("正在接收客戶端發送的文件..");
                        byte[] bs = new byte[1024];
                        int len = 0;
                        while ((len = in.read(bs)) != -1) {
                            //寫到文件中
                            fos.write(bs, 0, len);
                        }
                        System.out.println("服務器接收文件完畢...");
                        //        5.獲取通道中的輸出流(向客戶端發送反饋信息)
                        OutputStream out = client.getOutputStream();
                        out.write(("您的文件收到了,保存到服務器:" + filename).getBytes());
                        System.out.println("給客戶端發送反饋完畢...");
                        //        6.釋放資源
                        out.close();
                        fos.close();
                        in.close();
                        client.close();
                    } catch (IOException ie) {
                        ie.printStackTrace();
                    }
                }
            }).start();
        }
//        server.close();
//        System.out.println("服務器關閉成功...");
    }
}

        5.模擬BS架構服務器
        6.擴展:模擬服務器擴展——圖片顯示問題

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class BSServer {
    public static void main(String[] args) throws IOException {
        //1.創建服務器對象
        ServerSocket server = new ServerSocket(8888);
        while (true){
            //2.接收客戶端對象
            Socket socket = server.accept();
            System.out.println("有客戶端連接了,"+socket.getInetAddress().getHostAddress());
            new Thread(new Web(socket)).start();
        }
    }
}
class Web implements Runnable{
    private Socket socket;
    public Web(Socket socket){
        this.socket = socket;
    }

    @Override
    public void run() {
        try{
            //3.獲取通道中的輸入流
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            //4.讀取數據
            String line = null;
            //5.只需要讀取一行
            line = br.readLine(); //GET /1.html HTTP/1.1
            String[] names = line.split(" ");
            String filename = names[1].substring(1);
            System.out.println(filename);
            //通過文件的輸入流讀取文件
            FileInputStream fis = new FileInputStream(filename);
//            System.out.println(br.readLine());
//            while ((line = br.readLine())!=null){
//               System.out.println(line);
//           }

//        通過通道中的輸出流把文件發送給瀏覽器
            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());
            //循環
            byte[] b = new byte[1024];
            int len1 = 0;
            while ((len1 = fis.read(b))!=-1){
                out.write(b,0,len1);
            }
            //6.釋放資源
            out.close();
            fis.close();
            br.close();
            socket.close();
        }catch(IOException ie){
            ie.printStackTrace();
        }
    }
}


總結:
    -[] 能夠辨別UDP和TCP協議特點
    -[] 能夠說出TCP協議下兩個常用類名稱
            Socket    
            ServerSocket
    -[] 能夠編寫TCP協議下字符串數據傳輸程序****************
    -[] 能夠理解TCP協議下文件上傳案例
    -[] 能夠理解TCP協議下模擬B\S服務器案例


    


 

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