Java之Socket網(wǎng)絡(luò)編程

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

  • 網(wǎng)絡(luò)編程:指編寫運行在多個設(shè)備(計算機(jī))的程序,這些設(shè)備都通過網(wǎng)絡(luò)連接起來。

URL處理:http://www.baidu.com/search?code=Android&type=1

  • URL(Uniform Resource Locator)中文名為統(tǒng)一資源定位符,有時也被俗稱為網(wǎng)頁地址。
  • http/https :傳輸協(xié)議 TCP/IP協(xié)議
  • www.baidu.com :域名表示一臺網(wǎng)絡(luò)中的電腦
    (ipv4 ipv6 )IP地址:唯一標(biāo)識一臺網(wǎng)絡(luò)中的計算機(jī)
    ?? ?? ?? ?? 32位:4個部分 每部分8個字節(jié)
  • DNS服務(wù)器:域名解析 將www.baidu.com的域名解析為對應(yīng)的IP地址
  • search:對應(yīng)的后天程序文件 php java jsp
  • ? 表示運行這個程序需要傳遞的參數(shù)
  • code=Android code是服務(wù)器端規(guī)定的字段
  • & 如果有多個參數(shù)使用&連接

ps:查找自己的電腦IP:win+R進(jìn)入DOS窗口輸入ifconfig即可

  • 數(shù)據(jù)傳輸主要通過TCP/IP協(xié)議,以下是兩種常見的協(xié)議:
    • TCP(安全):TCP 是傳輸控制協(xié)議的縮寫,它保障了兩個應(yīng)用程序之間的可靠通信。通常用于互聯(lián)網(wǎng)協(xié)議,被稱 TCP / IP。

    • UDP(不安全,但是快):UDP 是用戶數(shù)據(jù)報協(xié)議的縮寫,一個無連接的協(xié)議。提供了應(yīng)用程序之間要發(fā)送的數(shù)據(jù)的數(shù)據(jù)包。

Socket 編程

相關(guān)概念

  • IP地址:唯一標(biāo)識某一臺電腦

  • 端口號:唯一標(biāo)識電腦上的某一個進(jìn)程(程序)80

  • Socket類:客戶端 手機(jī)應(yīng)用、瀏覽器等

  • ServerSocket:服務(wù)器端 存儲、處理數(shù)據(jù)

image.png

使用方法:

  • 讀取數(shù)據(jù):客戶端讀取 服務(wù)器端讀取
    BufferedReader->InputStreamReader->socket.getInputStream()
  • 讀取終端
    BufferedReader->InputStreamReader->System.in
  • 輸出:客戶端輸出 服務(wù)器端輸出
    BufferedWriter->OutputStreamWriter->serverSocket.getOutputStream()
    PrintStream(socket.getOutputStream)

1. 實現(xiàn)客戶端和服務(wù)器端傳遞數(shù)據(jù)(注意端?號必須相同 先運?Server 再運?Client)

客戶端:(1)創(chuàng)建用于通信的Socket,指明IP地址與端口號。
????????(2)使用BufferedReader用循環(huán)接收服務(wù)器端的數(shù)據(jù)。
????????(3)使用PrintStream向服務(wù)器端發(fā)送數(shù)據(jù),并告訴發(fā)送完成socket.shutdownOutput()。
服務(wù)器端:(1)創(chuàng)建服務(wù)器端的ServerSocket,并指明端口。
??????????(2)用serverSocket.accept()獲取連接客戶端的socket。
??????????(3)用PrintStream向客戶端發(fā)送數(shù)據(jù),完成時使用serverSocket.shutdownOutput()
??????????(4)使用BufferedReader接收客戶端發(fā)來的數(shù)據(jù)

模擬客戶端:

//模擬客戶端
//10.129.49.204
class Client{
    public static void main(String[] args) throws IOException {
        // 1.創(chuàng)建用于通信的Socket
        //  指明和誰通信:IP地址 端口號
        Socket socket = new Socket("10.129.25.52",8989);
        //接收服務(wù)器端發(fā)來的數(shù)據(jù)
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        // 向服務(wù)器端發(fā)送數(shù)據(jù)
        // socket.getOutputStream();
        String line = null;
        while ((line = br.readLine()) != null){
            System.out.println(line);
        }

        //客戶端向服務(wù)器端發(fā)送數(shù)據(jù)
        PrintStream ps = new PrintStream(socket.getOutputStream());
        ps.println("你好啊!!!");

        socket.shutdownOutput();
    }
}

模擬服務(wù)器端:

class Server{
    public static void main(String[] args) throws IOException {
        //1.創(chuàng)建服務(wù)器的serversocket
        ServerSocket ss = new ServerSocket(8989);

        //2.獲取連接的客戶端的socket
        Socket clientSocket = ss.accept();

        //3.向客戶端發(fā)送數(shù)據(jù)
        // BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
        PrintStream ps = new PrintStream(clientSocket.getOutputStream());
        ps.println("登錄成功");

        //輸出完畢
        clientSocket.shutdownOutput();

        // 4.接收客戶端發(fā)來的數(shù)據(jù)
        BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        String line = null;
        while ((line = br.readLine()) != null){
            System.out.println(line);
        }
    }
}

2. 手動輸入內(nèi)容發(fā)送,將輸?的內(nèi)容發(fā)送給客戶端 可以?直發(fā)

異常處理:如果出現(xiàn)異常,按從小到大關(guān)閉資源

兩種方式處理異常:

  • 方式1使用if判斷語句
 Socket socket = null;
        try {
            socket = new Socket("10.129.49.204",8888);

            //接收服務(wù)器端信息
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String line = null;
            while ((line = br.readLine()) != null){
                System.out.println(line);
            }
        } catch (IOException e) {
            System.out.println("網(wǎng)絡(luò)出錯,請重新登錄");
        }finally {
            // 關(guān)閉連接
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
  • 方式2
 try( ServerSocket serverSocket = new ServerSocket(8888)) {
            // 監(jiān)聽客戶端
            Socket socket = serverSocket.accept();

            // 從終端接收數(shù)據(jù)發(fā)送給客戶端
            BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
            //獲取向客戶端輸出數(shù)據(jù)的輸出流
            PrintStream ps = new PrintStream(socket.getOutputStream());
            String line = null;

            while ((line = keyin.readLine()) != null){
                // 發(fā)送給客戶端
                ps.println(line);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
class MyClient{
    public static void main(String[] args){
        //連接服務(wù)器端的socket
        Socket socket = null;
        try {
            socket = new Socket("10.129.49.204",8888);

            //接收服務(wù)器端信息
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String line = null;
            while ((line = br.readLine()) != null){
                System.out.println(line);
            }

        } catch (IOException e) {
            System.out.println("網(wǎng)絡(luò)出錯,請重新登錄");
        }finally {
            // 關(guān)閉連接
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}


class MyServer{
    public static void main(String[] args){
        //創(chuàng)建ServerSocket  自動關(guān)閉
        try( ServerSocket serverSocket = new ServerSocket(8888)) {
            // 監(jiān)聽客戶端
            Socket socket = serverSocket.accept();

            // 從終端接收數(shù)據(jù)發(fā)送給客戶端
            BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
            //獲取向客戶端輸出數(shù)據(jù)的輸出流
            PrintStream ps = new PrintStream(socket.getOutputStream());
            String line = null;

            while ((line = keyin.readLine()) != null){
                // 發(fā)送給客戶端
                ps.println(line);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

3. 實現(xiàn)客戶端向服務(wù)器端上傳圖?(字節(jié)流)

class Client{
    public static void main(String[] args) throws IOException {
        //鏈接服務(wù)器端  獲取socket
        Socket socket = new Socket("10.129.49.204",8080);

        //創(chuàng)建服務(wù)器端對應(yīng)的輸入流 用于接受服務(wù)器端發(fā)來的數(shù)據(jù)
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
       System.out.println( bufferedReader.readLine());

       //向服務(wù)器端發(fā)送文件(圖片)
        String path = "C:\\Users\\gyl\\Desktop\\1.jpg";
        //1. 將文件寫入到內(nèi)存
        FileInputStream fis = new FileInputStream(path);

        // 2 .創(chuàng)建字節(jié)流 outputStream
        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        byte[] buffer = new byte[1024];
        int length = -1;
        while ((length = fis.read(buffer)) != -1){
            bos.write(buffer,0,length);
        }
        socket.shutdownOutput();


    }
}


class Server{
    public static void main(String[] args) throws IOException {
        //創(chuàng)建服務(wù)器的serverSocket
        ServerSocket serverSocket = new ServerSocket(8080);

        //監(jiān)聽客戶端連接
        //當(dāng)有客戶端來連接這個服務(wù)器  就可以得到對應(yīng)的socket
        //當(dāng)沒有客戶端來連接 服務(wù)器一直在這里等待
        Socket socket = serverSocket.accept();

        //創(chuàng)建客戶端對應(yīng)的輸出流對象 用于向這個客戶端發(fā)送數(shù)據(jù)
        PrintStream printStream = new PrintStream(socket.getOutputStream());
        printStream.println("連接成功  可以發(fā)送數(shù)據(jù)了");

        // 接收客戶端傳遞過來的圖片
        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
        //文件對應(yīng)的輸出流
        String path = "D:\\AndroidStudioProjects\\JavaCourse\\Java\\src\\main\\java\\day12\\media\\1.jpg";
        FileOutputStream fos = new FileOutputStream(path);

        byte[] buffer = new byte[1024];
        int length = -1;
        while ((length = bis.read(buffer)) != -1){
            fos.write(buffer,0,length);
        }
    }
}

4.使?多線程實現(xiàn)對聊

  • 創(chuàng)建一個類實現(xiàn)Runnable接口,重寫run方法
  • 創(chuàng)建一個類繼承于Thread類,重寫run方法
/**
 * 客戶端和服務(wù)器端可以隨意的發(fā)送內(nèi)容
 * 從終端輸入
 *
 * 客戶端:
 *          主線程:接收終端輸入   將終端的輸入發(fā)送給服務(wù)器端
 *          子線程:接收服務(wù)器端發(fā)送過來的數(shù)據(jù)
 * 服務(wù)器端:
 *          主線程:接收終端輸入   將終端的輸入發(fā)送給客戶端
 *           子線程:接收客戶端發(fā)送過來的數(shù)據(jù)
 */

class Cilent{
    public static void main(String[] args) throws IOException {
        //鏈接服務(wù)器端 獲取socket
        Socket socket = new Socket("10.129.49.204",8888);

        // 用一個子線程處理服務(wù)器端的數(shù)據(jù)
        new Thread(new ClientThread(socket)).start();

        // 主線程處理終端輸入發(fā)送給服務(wù)器端
        BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
        PrintStream ps = new PrintStream(socket.getOutputStream());
        String line = null;

        while ((line = keyin.readLine()) != null){
            ps.println(line);
        }

    }
}


/**
 * 創(chuàng)建一個子線程 處理客戶端接收服務(wù)器的數(shù)據(jù)
 */
class ClientThread implements Runnable{
    private Socket socket;
    // 保存socket對象
    public ClientThread(Socket socket){
        this.socket = socket;
    }

    @Override
    public void run() {
        BufferedReader br = null;
        try {
            // 獲取服務(wù)器端的輸入流
            br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

             // 讀取數(shù)據(jù)
            String line = null;
            while ((line = br.readLine()) != null){
                System.out.println(line);
            }
        } catch (IOException e) {
            System.out.println("網(wǎng)絡(luò)出錯  請重新登錄");
            System.exit(-1);
        }finally {
            // 出現(xiàn)異常 關(guān)閉資源 從小到大
            try {
            if (br != null){
                    br.close();
                }
            if (socket != null){
                socket.close();
            }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

class Server{
    public static void main(String[] args) throws IOException {
        // 創(chuàng)建服務(wù)器端
        ServerSocket ss = new ServerSocket(8888);
        // 獲取客戶端的socket
        Socket socket = ss.accept();

        // 創(chuàng)建子線程 處理客戶端輸入信息
        new ServerThread(socket).start();

        //終端輸入流對象
        BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
        // 客戶端輸出流對象
        PrintStream ps = new PrintStream(socket.getOutputStream());
        // 讀取終端的輸入 將輸入輸出給客戶端
        String line = null;
        while ((line = keyin.readLine()) != null){
            ps.println(line);
        }
    }
}

/**
 *  創(chuàng)建一個子線程處理服務(wù)器端接收客戶端的書據(jù)
 */

class ServerThread extends Thread{
    private Socket socket;
    public ServerThread(Socket socket){
        this.socket = socket;
    }

    @Override
    public void run() {
        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String line = null;

            while ((line = br.readLine()) != null){
                System.out.println(line);
            }
        } catch (IOException e) {
           System.out.println("網(wǎng)絡(luò)異常  請重新登錄");
           System.exit(-1);
        }finally {
            // 關(guān)閉輸入輸出流
            // 關(guān)閉對應(yīng)的socket鏈接
            try {
                if (br != null) {
                    br.close();
                }
                if (socket != null) {
                    socket.close();
                }
            }catch(IOException e){
                e.printStackTrace();
            }
        }
    }
}

5.實現(xiàn)群聊

  • 使用ArrayList 保存每一個連接到的客戶端,并且通過循環(huán)依次將信息發(fā)送給每一個客戶端。
class Server{
    // 保存每一個鏈接過來的對象
    public static ArrayList<Socket> sockets = new ArrayList<>();
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(8888);

        //不停地等待客戶端來連接
        while (true){
            Socket socket = ss.accept();
            // 當(dāng)有客戶端連接過來了就保存
            sockets.add(socket);

            //開啟一個線程處理每個客戶端的輸入
            new ServerThread(socket).start();

        }

    }
}

/**
 *  創(chuàng)建一個子線程處理服務(wù)器端接收客戶端的書據(jù)
 */

class ServerThread extends Thread{
    private Socket socket;
    public ServerThread(Socket socket){
        this.socket = socket;
    }

    @Override
    public void run() {
        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String line = null;

            while ((line = br.readLine()) != null){
                // 群發(fā)消息
                // 遍歷Server維護(hù)的數(shù)組
                for (Socket socket:Server.sockets){
                    // 想socket對應(yīng)的客戶端發(fā)送信息
                    PrintStream s = new PrintStream(socket.getOutputStream());
                    s.println(line);
                }
            }
        } catch (IOException e) {
            System.out.println("網(wǎng)絡(luò)異常  請重新登錄");
            System.exit(-1);
        }finally {
            // 關(guān)閉輸入輸出流
            // 關(guān)閉對應(yīng)的socket鏈接
            try {
                if (br != null) {
                    br.close();
                }
                if (socket != null) {
                    socket.close();
                }
            }catch(IOException e){
                e.printStackTrace();
            }
        }
    }
}

class Cilent{
    public static void main(String[] args) throws IOException {
        //鏈接服務(wù)器端 獲取socket
        Socket socket = new Socket("10.129.49.204",8888);

        // 用一個子線程處理服務(wù)器端的數(shù)據(jù)
        new Thread(new ClientThread(socket)).start();

        // 主線程處理終端輸入發(fā)送給服務(wù)器端
        BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
        PrintStream ps = new PrintStream(socket.getOutputStream());
        String line = null;

        while ((line = keyin.readLine()) != null){
            ps.println(line);
        }



    }
}

/**
 * 創(chuàng)建一個子線程 處理客戶端接收服務(wù)器的數(shù)據(jù)
 */
class ClientThread implements Runnable{
    private Socket socket;
    // 保存socket對象
    public ClientThread(Socket socket){
        this.socket = socket;
    }

    @Override
    public void run() {
        BufferedReader br = null;
        try {
            // 獲取服務(wù)器端的輸入流
            br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            // 讀取數(shù)據(jù)
            String line = null;
            while ((line = br.readLine()) != null){
                System.out.println(line);
            }
        } catch (IOException e) {
            System.out.println("網(wǎng)絡(luò)出錯  請重新登錄");
            System.exit(-1);
        }finally {
            // 出現(xiàn)異常 關(guān)閉資源 從小到大
            try {
                if (br != null){
                    br.close();
                }
                if (socket != null){
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

心得體會

??關(guān)于客戶端和服務(wù)器端的操作,剛開始對于輸入輸出有點繞,不過多寫了幾遍之后,就更清楚了 ,類似于模板。同時又將多線程的知識融入進(jìn)來,對知識的理解也更加深刻了。

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

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

  • 計算機(jī)網(wǎng)絡(luò)概述 網(wǎng)絡(luò)編程的實質(zhì)就是兩個(或多個)設(shè)備(例如計算機(jī))之間的數(shù)據(jù)傳輸。 按照計算機(jī)網(wǎng)絡(luò)的定義,通過一定...
    蛋炒飯_By閱讀 1,367評論 0 10
  • 1 網(wǎng)絡(luò)編程----TCPNo24 【 public class Server { public static...
    征程_Journey閱讀 1,380評論 0 4
  • 網(wǎng)絡(luò)編程的概述 網(wǎng)絡(luò)編程的實質(zhì)就是用來實現(xiàn)網(wǎng)絡(luò)互連的不同計算機(jī)上運行的程序間可以進(jìn)行數(shù)據(jù)交換。 一.OSI網(wǎng)絡(luò)模型...
    思念揮霍閱讀 437評論 0 0
  • 7.2 面向套接字編程我們已經(jīng)通過了解Socket的接口,知其所以然,下面我們就將通過具體的案例,來熟悉Socke...
    lucas777閱讀 1,276評論 0 2
  • 早上六點溜達(dá)到8點多,風(fēng)起時,風(fēng)車沙沙,你專注撫弄風(fēng)車,激動喊著:轉(zhuǎn)!轉(zhuǎn)!還是相信孟子“性善論”,孩子是沒有破壞意...
    若懂得閱讀 190評論 0 1

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