国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

JavaEE 初階篇-深入了解 UDP 通信與 TCP 通信(綜合案例:實現(xiàn) TCP 通信群聊)

這篇具有很好參考價值的文章主要介紹了JavaEE 初階篇-深入了解 UDP 通信與 TCP 通信(綜合案例:實現(xiàn) TCP 通信群聊)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

??博客主頁:?【小扳_-CSDN博客】
?感謝大家點贊??收藏?評論?

JavaEE 初階篇-深入了解 UDP 通信與 TCP 通信(綜合案例:實現(xiàn) TCP 通信群聊),JavaEE 初級篇,udp,tcp/ip,網(wǎng)絡(luò),java,java-ee,開發(fā)語言,大數(shù)據(jù)

JavaEE 初階篇-深入了解 UDP 通信與 TCP 通信(綜合案例:實現(xiàn) TCP 通信群聊),JavaEE 初級篇,udp,tcp/ip,網(wǎng)絡(luò),java,java-ee,開發(fā)語言,大數(shù)據(jù)

文章目錄

? ? ? ? 1.0 UDP 通信

????????1.1 DatagramSocket 類

????????1.2 DatagramPacket 類

????????1.3 實現(xiàn) UDP 通信(一發(fā)一收)

? ? ? ? 1.3.1 客戶端的開發(fā)

? ? ? ? 1.3.2 服務(wù)端的開發(fā)

????????1.4 實現(xiàn) UDP 通信(多發(fā)多收)

? ? ? ? 1.4.1 客戶端的開發(fā)

? ? ? ? 1.4.2 服務(wù)端的開發(fā)

? ? ? ? 2.0 TCP 網(wǎng)絡(luò)通信

? ? ? ? 2.1 Socket 類

????????2.2 ServerSocket 類

? ? ? ? 2.3 實現(xiàn) TCP 網(wǎng)絡(luò)通信(一發(fā)一收)

????????2.3.1 客戶端的開發(fā)

? ? ? ? 2.3.2 服務(wù)端的開發(fā)

? ? ? ? 2.4?實現(xiàn) TCP 網(wǎng)絡(luò)通信(多發(fā)多收)

? ? ? ? 2.4.1 客戶端的開發(fā)

? ? ? ? 2.4.2 服務(wù)端的開發(fā)

? ? ? ? 2.5 實現(xiàn) TCP 網(wǎng)絡(luò)通信(支持與多個客戶端通信)

? ? ? ? 2.6 實現(xiàn) TCP 網(wǎng)絡(luò)通信(綜合案例:群聊)

? ? ? ? 2.6.1 客戶端的開發(fā)

? ? ? ? 2.6.2 服務(wù)端的開發(fā)


? ? ? ? 1.0 UDP 通信

? ? ? ? 無連接、不可靠通信。

? ? ? ? 不事先建立連接;發(fā)送端每次把要發(fā)送的數(shù)據(jù)(限制在 64 KB 內(nèi))、接收端 IP 等信息封裝成一個數(shù)據(jù)包,發(fā)出去就不管了。

? ? ? ? Java 提供了一個 Java.net.DatagramSocket 類來實現(xiàn) UDP 通信。

????????1.1 DatagramSocket 類

? ? ? ? 用于創(chuàng)建客戶端、服務(wù)端。Java 中用于實現(xiàn) UDP 協(xié)議的套接字類,用于創(chuàng)建 UDP 套接字并進行數(shù)據(jù)傳輸。UDP 是無連接的、不可靠的傳輸協(xié)議,適用于一些要求實時性較高、容忍少量數(shù)據(jù)丟失的應(yīng)用場景。

構(gòu)造器:

? ? ? ? 1)public DatagramSocket():創(chuàng)建客戶端的 Socket 對象,系統(tǒng)會隨機分配一個端口號。

? ? ? ? 2)public DatagramSocket(int port):創(chuàng)建服務(wù)端的 Socket 兌現(xiàn),并指定端口號。

方法:

? ? ? ? 1)public void send(DatagramPacket dp):發(fā)送數(shù)據(jù)包。

? ? ? ? 2)public void receive(DatagramPacket p):使用數(shù)據(jù)包接收數(shù)據(jù)。

? ? ? ? 3)public void close():關(guān)閉 UDP 套接字。

????????1.2 DatagramPacket 類

? ? ? ? 創(chuàng)建數(shù)據(jù)包。用于在 UDP 通信中封裝數(shù)據(jù)和目標地址信息。DatagramPacket 類包含了要發(fā)送或接收的數(shù)據(jù)、數(shù)據(jù)的長度、目標地址和端口等信息。

構(gòu)造器:

? ? ? ? 1)public DatagramPacket(byte[] buf,int length,InetAddress address,int port):創(chuàng)建發(fā)出去的數(shù)據(jù)包對象。

? ? ? ? 2)public DatagramPacket(byte[] buf,int length):創(chuàng)建用來接收的數(shù)據(jù)的數(shù)據(jù)包。

方法:

? ? ? ? 1)getData():獲取數(shù)據(jù) 數(shù)據(jù)的字節(jié)數(shù)組。

? ? ? ? 2)getLength():獲取數(shù)據(jù)的長度。字節(jié)數(shù)組的長度。

? ? ? ? 3)getAddress():獲取數(shù)據(jù)報的目標地址。返回的是 InetAddress 類對象,即接收的 IP 對象。

? ? ? ? 4)getPort():獲取數(shù)據(jù)報的目標端口。

????????1.3 實現(xiàn) UDP 通信(一發(fā)一收)

? ? ? ? 整個的過程可以比作:廚師將碟子上的“炒粉”隔空拋出去給服務(wù)員(客戶端發(fā)消息過程),服務(wù)員用碟子接收“炒粉”(服務(wù)端接收消息過程)。注意的是拋出去的只是“炒粉”,而碟子是不拋出去的。

? ? ? ? 1.3.1 客戶端的開發(fā)

????????廚師將碟子上的“炒粉”隔空拋出去給服務(wù)員(客戶端發(fā)消息過程)。

? ? ? ? 首先是對客戶端的開發(fā),先創(chuàng)建客戶端對象,利用無參構(gòu)造器 DatagramSocket() 來創(chuàng)建一個由系統(tǒng)分配的 IP 地址的客戶端對象。把客戶端對象可以比作成一個廚師。

? ? ? ? 再來創(chuàng)建發(fā)出去的數(shù)據(jù)包對象,利用 DatagramPacket(byte[] buf,int length,InetAddress address,int port) 構(gòu)造器來創(chuàng)建數(shù)據(jù)包對象。把數(shù)據(jù)包對象可以比作廚師手上的碟子,其中參數(shù) buf 是存放數(shù)據(jù)的容器,把 buf 比如碟子上盛的“炒粉”,參數(shù) length 是用來記錄發(fā)送數(shù)據(jù)的大小,參數(shù) address 是發(fā)送的 IP 地址對象,將 address 可以比作碟子上的“炒粉”通過 address 來定位到具體要發(fā)送的目標服務(wù)員。參數(shù) port 是用來記錄發(fā)送的目標程序即端口號。

代碼如下:

import java.io.IOException;
import java.net.*;

public class demo1 {
    public static void main(String[] args) throws IOException {
        DatagramSocket socket = new DatagramSocket();
        
        String msg = "需要發(fā)送的消息";
        //將字符串轉(zhuǎn)化為字節(jié)數(shù)組
        byte[] m = msg.getBytes();
        //假如:發(fā)送的地方正是本機,就可以通過 InetAddress.getLocalHost() 方法來獲取到 IP 地址對象,
        //發(fā)送的程序端口號假設(shè)為: 8888
        DatagramPacket packet = new DatagramPacket(m,m.length, InetAddress.getLocalHost(),8888);
        //接著就可以發(fā)送消息了
        socket.send(packet);
        
        //最后記得要關(guān)閉資源
        socket.close();
        
    }
}

? ? ? ? 廚師將碟子上的“炒粉”隔空拋出去給服務(wù)員,服務(wù)員用碟子接收“炒粉”。注意的是拋出去的只是“炒粉”,而碟子是不拋出去的。

? ? ? ? 1.3.2 服務(wù)端的開發(fā)

? ? ? ??服務(wù)員用碟子接收“炒粉”(服務(wù)端接收消息過程)。

? ? ? ? 首先創(chuàng)建服務(wù)端對象,利用有參構(gòu)造器 DatagramSocket(8888) 來創(chuàng)建端口號為 8888 的服務(wù)端對象。

????????這里用到有參構(gòu)造器來創(chuàng)建指定的端口號是因為:為了其他客戶端精確無誤的發(fā)送消息到目標程序上。不用無參構(gòu)造器的是因為:利用無參構(gòu)造器創(chuàng)建的服務(wù)端是由系統(tǒng)隨機分配端口號,不利于其他客戶端訪問服務(wù)端。

? ? ? ? 接著創(chuàng)建接收數(shù)據(jù)的數(shù)據(jù)包對象,利用 DatagramPacket(byte[] buf,int length) 構(gòu)造器來創(chuàng)建數(shù)據(jù)包對象,用來接收數(shù)據(jù)。

? ? ? ? 接收完畢之后,需要關(guān)閉資源。

代碼如下:

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

public class Server {
    public static void main(String[] args) throws IOException {
        //創(chuàng)建服務(wù)端對象,且指定端口號
        DatagramSocket socket = new DatagramSocket(8888);

        //創(chuàng)建數(shù)據(jù)包對象
        //接收數(shù)據(jù)的容器的大小,最大發(fā)送過來的數(shù)據(jù)大小不會超過64KB,
        //因此用64KB大小的字節(jié)數(shù)組來接收數(shù)據(jù)
        byte[] bytes = new byte[1024*64];
        DatagramPacket packet = new DatagramPacket(bytes,bytes.length);
        //此時就可以用數(shù)據(jù)包來接收數(shù)據(jù)了
        socket.receive(packet);

        //輸出數(shù)據(jù)
        byte[] data = packet.getData();
        //轉(zhuǎn)化為字符串
        String str = new String(data,0,packet.getLength());
        System.out.println(str);
        //還可以獲取到客戶端的IP對象、客戶端的IP對象地址、端口號
        InetAddress client = packet.getAddress();
        String address = client.getHostAddress();
        int clientPort = packet.getPort();
        System.out.println("客戶端IP地址:" + address + " , " + "客戶端端口號:" + clientPort);

        //關(guān)閉資源
        socket.close();

    }
}

????????1.4 實現(xiàn) UDP 通信(多發(fā)多收)

? ? ? ? 客戶端可以多次發(fā)送消息給服務(wù)端,服務(wù)端可以多次接收客戶端發(fā)送的消息。

? ? ? ? 1.4.1 客戶端的開發(fā)

? ? ? ? 在以上代碼進行改造,對發(fā)送消息的代碼設(shè)置循環(huán)。注意退出程序的時候需要關(guān)閉資源。

import java.io.IOException;
import java.net.*;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) throws IOException {
        DatagramSocket socket = new DatagramSocket();
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("請輸出需要發(fā)送的消息:");
            String msg = scanner.nextLine();
            if ("exit".equals(msg)){
                System.out.println("成功退出!!!");
                //最后記得要關(guān)閉
                socket.close();
                break;
            }
            //將字符串轉(zhuǎn)化為字節(jié)數(shù)組
            byte[] m = msg.getBytes();
            //假如:發(fā)送的地方正是本機,就可以通過 InetAddress.getLocalHost() 方法來獲取到 IP 地址對象,
            //發(fā)送的程序端口號假設(shè)為: 8888
            DatagramPacket packet = new DatagramPacket(m,m.length, InetAddress.getLocalHost(),8888);
            //接著就可以發(fā)送消息了
            socket.send(packet);
        }
    }
}

? ? ? ? 1.4.2 服務(wù)端的開發(fā)

? ? ? ? 設(shè)置循環(huán)接收消息。其實對于服務(wù)端來說,不應(yīng)該關(guān)閉資源,因為隨時等待著客戶端來訪問。

代碼如下:

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

public class Server {
    public static void main(String[] args) throws IOException {
        //創(chuàng)建服務(wù)端對象,且指定端口號
        DatagramSocket socket = new DatagramSocket(8888);

        //創(chuàng)建數(shù)據(jù)包對象
        //接收數(shù)據(jù)的容器的大小,最大發(fā)送過來的數(shù)據(jù)大小不會超過64KB,
        //因此用64KB大小的字節(jié)數(shù)組來接收數(shù)據(jù)
        byte[] bytes = new byte[1024*64];
        DatagramPacket packet = new DatagramPacket(bytes,bytes.length);


        while (true) {
            //此時就可以用數(shù)據(jù)包來接收數(shù)據(jù)了
            socket.receive(packet);

            //輸出數(shù)據(jù)
            byte[] data = packet.getData();
            //轉(zhuǎn)化為字符串
            String str = new String(data,0,packet.getLength());
            System.out.println(str);
            //還可以獲取到客戶端的IP對象、客戶端的IP對象地址、端口號
            InetAddress client = packet.getAddress();
            String address = client.getHostAddress();
            int clientPort = packet.getPort();
            System.out.println("客戶端IP地址:" + address + " , " + "客戶端端口號:" + clientPort);
            System.out.println("========================");
        }

/*        //關(guān)閉資源
        socket.close();*/

    }
}

運行結(jié)果:

服務(wù)端:

JavaEE 初階篇-深入了解 UDP 通信與 TCP 通信(綜合案例:實現(xiàn) TCP 通信群聊),JavaEE 初級篇,udp,tcp/ip,網(wǎng)絡(luò),java,java-ee,開發(fā)語言,大數(shù)據(jù)

客戶端:

JavaEE 初階篇-深入了解 UDP 通信與 TCP 通信(綜合案例:實現(xiàn) TCP 通信群聊),JavaEE 初級篇,udp,tcp/ip,網(wǎng)絡(luò),java,java-ee,開發(fā)語言,大數(shù)據(jù)

? ? ? ? 需要注意的是:在啟動程序的時候,應(yīng)該先啟動服務(wù)端程序,再啟動客戶端程序。

? ? ? ? 2.0 TCP 網(wǎng)絡(luò)通信

? ? ? ? 面向連接、可靠連接。

? ? ? ? 2.1 Socket 類

? ? ? ??Java 中用于實現(xiàn) TCP 通信的類,主要用于在客戶端和服務(wù)器之間建立 TCP 連接。通過 Socket 類,可以在客戶端和服務(wù)器之間進行雙向通信,實現(xiàn)數(shù)據(jù)的傳輸和交互。

? ? ? ? 1)創(chuàng)建 Socket 對象:通過 Socket 類的構(gòu)造方法可以創(chuàng)建一個 Socket 對象,用于表示客戶端與服務(wù)器之間的 TCP 連接。可以連接指定的服務(wù)器和端口。

? ? ? ? 2)發(fā)送數(shù)據(jù):通過 Socket 類的 getOutputStream 方法獲取輸出流,可以向服務(wù)器發(fā)送數(shù)據(jù)。

? ? ? ? 3)接收數(shù)據(jù):通過 Socket 類的 getInputStream 方法獲取輸入流,可以從服務(wù)器接收數(shù)據(jù)。

? ? ? ? 4)關(guān)閉連接:通過 Socket 類的 close 方法可以關(guān)閉 TCP 連接。

其他常用的方法:

? ? ? ? 1)getInetAddress() 方法:獲取遠程主機的地址,返回 InetAddress 對象。

? ? ? ? 2)getPort() 方法:獲取遠程主機的端口號。

? ? ? ? 3)getLocalAddress() 方法:獲取本地主機的地址,返回 InetAddress 對象。

? ? ? ? 4)getLocalPort() 方法:獲取本地主機的端口號。

? ? ? ? 簡單來說,通過構(gòu)造方法指定的 IP 地址和端口號來創(chuàng)建的客戶端與指定的服務(wù)器建立連接。建立連接相當于創(chuàng)建了管道。創(chuàng)建管道來支持字節(jié)流的發(fā)送或者接收。通過 getOutputStream 方法或者 getInputStream 方法來發(fā)送或者接收字節(jié)流。

????????2.2 ServerSocket 類

????????Java 中用于實現(xiàn) TCP 服務(wù)器端的類,它用于監(jiān)聽客戶端的連接請求并創(chuàng)建對應(yīng)的 Socket 對象進行通信。

構(gòu)造方法:

????????ServerSocket(int port) 構(gòu)造方法:創(chuàng)建一個新的 ServerSocket 對象,綁定到指定的端口。

常用的方法:

? ? ? ? 1)accept() 方法:監(jiān)聽并接受客戶端的連接請求,返回一個新的 Socket 對象用于與客戶端通信。

? ? ? ? 2)close() 方法:關(guān)閉 ServerSocket 對象,停止監(jiān)聽新的連接請求。

? ? ? ? 3)getInetAddress() 方法:獲取 ServerSocket?綁定的本地地址。

? ? ? ? 4)getLocalPort() 方法:獲取 ServerSocket 綁定的本地端口號。

????????ServerSocket 類用于在服務(wù)器端監(jiān)聽客戶端的連接請求,并創(chuàng)建對應(yīng)的 Socket 對象用于與客戶端進行通信。通過 ServerSocket 類提供的方法,您可以管理服務(wù)器端的 TCP 連接、設(shè)置相關(guān)參數(shù)以及處理客戶端的連接請求。類用于在服務(wù)器端監(jiān)聽客戶端的連接請求,并創(chuàng)建對應(yīng)的 Socket?對象用于與客戶端進行通信。通過 ServerSocket 類提供的方法,您可以管理服務(wù)器端的 TCP 連接、設(shè)置相關(guān)參數(shù)以及處理客戶端的連接請求。

? ? ? ? 2.3 實現(xiàn) TCP 網(wǎng)絡(luò)通信(一發(fā)一收)

????????2.3.1 客戶端的開發(fā)

? ? ? ? 先創(chuàng)建管道對象,利用有參構(gòu)造器 Socket(String host,int port) 創(chuàng)建連接指定的服務(wù)器的管道。接著,利用 Socket 對象提供的方法 getOutputStream() 方法來獲取字節(jié)輸出流對象,利用該對象進行寫操作,最后發(fā)送完畢之后,需要關(guān)閉資源。

代碼如下:

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

public class Client {
    public static void main(String[] args) throws IOException {
        //創(chuàng)建管道對象
        Socket socket = new Socket("127.0.0.1",8888);

        //獲取到輸出流
        OutputStream os = socket.getOutputStream();
        //將其低級的輸出流升級為高級的輸出流
        DataOutputStream dos = new DataOutputStream(os);

        dos.writeUTF("需要發(fā)送的消息!!!");

        //關(guān)閉資源
        dos.close();
        socket.close();

    }
}

? ? ? ? 注意關(guān)閉資源的順序,先關(guān)閉后開啟的資源,再關(guān)閉前面開啟的資源。

? ? ? ? 2.3.2 服務(wù)端的開發(fā)

? ? ? ? 先創(chuàng)建 ServerSocket 類,用有參構(gòu)造器 ServerSocket(int port) 創(chuàng)建指定端口號的對象,再用 accept() 方法來等待接收來自客戶端發(fā)送來的連接請求,客戶端與服務(wù)端連接完畢之后,就會返回一個 Socket 對象給服務(wù)端,該 Socket 對象可以理解為管道的服務(wù)器的一端,客戶端已經(jīng)有 Socket 對象了,該對象就可以理解為管道的客戶端的一端。

? ? ? ? 接著,通過 Socket 提供的方法來獲取二進制輸出流對象或者是二進制輸入流對象,通過管道將數(shù)據(jù)進行傳輸?shù)娇蛻舳恕?/strong>

代碼如下:

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

public class Server {
    public static void main(String[] args) throws IOException {
        //創(chuàng)建服務(wù)端,并指定端口號
        ServerSocket serverSocket = new ServerSocket(8888);

        //等待客戶端發(fā)送消息來獲取管道對象
        Socket socket = serverSocket.accept();
        //通過管道對象再來獲取到讀取流對象
        InputStream inputStream = socket.getInputStream();
        //再將低級流轉(zhuǎn)化為高級流
        DataInputStream dis = new DataInputStream(inputStream);
        String s = dis.readUTF();
        System.out.println(s);

        //關(guān)閉資源
        dis.close();
        socket.close();

    }
}

運行結(jié)果:

JavaEE 初階篇-深入了解 UDP 通信與 TCP 通信(綜合案例:實現(xiàn) TCP 通信群聊),JavaEE 初級篇,udp,tcp/ip,網(wǎng)絡(luò),java,java-ee,開發(fā)語言,大數(shù)據(jù)

????????客戶端發(fā)送數(shù)據(jù),服務(wù)端接收數(shù)據(jù)的代碼就實現(xiàn)了。

? ? ? ? 2.4?實現(xiàn) TCP 網(wǎng)絡(luò)通信(多發(fā)多收)

? ? ? ? 2.4.1 客戶端的開發(fā)

? ? ? ? 將以上客戶端的代碼輸出數(shù)據(jù)進行循環(huán)即可,每次輸出完數(shù)據(jù)之后,最好刷新一下。

代碼如下:

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class MyClient {
    //TCP 實現(xiàn)多發(fā)多收
    public static void main(String[] args) throws IOException {
        //創(chuàng)建管道對象
        Socket socket = new Socket("127.0.0.1",8888);
        //獲取寫數(shù)據(jù)流
        OutputStream os = socket.getOutputStream();
        //將低級流轉(zhuǎn)換為高級流
        DataOutputStream dos = new DataOutputStream(os);
        Scanner scanner = new Scanner(System.in);

        while (true) {
            String msg = scanner.nextLine();
            if ("exit".equals(msg)){
                System.out.println("退出成功!!!!");
                //關(guān)閉資源
                dos.close();
                socket.close();
                break;
            }
            //寫數(shù)據(jù)
            dos.writeUTF(msg);
            //刷新數(shù)據(jù),將緩存的數(shù)據(jù)進行刷新
            dos.flush();
        }
    }
}

? ? ? ? 2.4.2 服務(wù)端的開發(fā)

? ? ? ? 將以上服務(wù)端的輸入數(shù)據(jù)的代碼加上循環(huán)即可,需要注意的是:在客戶端管道一端假設(shè)要斷開連接的時候,此時服務(wù)端還在連接著管道,這就會導致服務(wù)端一端會報異常,因此,需要對服務(wù)端輸入數(shù)據(jù)這一段代碼加上 try-catch 捕獲異常處理。

代碼如下:

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class MyServer {
    public static void main(String[] args) throws IOException {
        //創(chuàng)建服務(wù)端管道對象
        ServerSocket serverSocket = new ServerSocket(8888);

        //等待接收客戶端,創(chuàng)建管道對象
        Socket socket = serverSocket.accept();
        //創(chuàng)建完管道之后,就要創(chuàng)建字節(jié)流
        InputStream inputStream = socket.getInputStream();
        //再將低級流升級為高級流
        DataInputStream dis = new DataInputStream(inputStream);

        while (true) {
            try {
                //接著就可以讀數(shù)據(jù)了
                String s = dis.readUTF();
                System.out.println(s);
                //通過管道對象來獲取到發(fā)送消息的IP對象
                InetAddress clientInetAddress = socket.getInetAddress();
                //socket.getRemoteSocketAddress()
                //通過管道對象就可以獲取到端口號
                int clientPort = socket.getPort();
                //通過IP對象就可以獲取到IP地址
                String address = clientInetAddress.getHostAddress();
                //通過IP對象就可以獲取到IP名字
                String clientName = clientInetAddress.getHostName();
                System.out.println("端口號: "+ clientPort + " ,IP名字: " + clientName + " ,IP地址: " + address);
                System.out.println("=====================");
            } catch (IOException e) {
                System.out.println(" IP名字: " + socket.getInetAddress().getHostName() + " ,IP地址: " + socket.getInetAddress().getHostAddress() + " 離線了!!!");
                dis.close();
                socket.close();
                break;
            }
        }
    }
}

? ? ? ? 2.5 實現(xiàn) TCP 網(wǎng)絡(luò)通信(支持與多個客戶端通信)

? ? ? ? 實現(xiàn)思路:當前服務(wù)端只有主線程負責一個客戶端進行通信,那么實現(xiàn)服務(wù)端與多個客戶端實現(xiàn)通信需要實現(xiàn)多線程,在服務(wù)端中創(chuàng)建多個線程,每一個線程都對應(yīng)一個客戶端進行通信,而主線線程將將接收到的 Socket 對象通過構(gòu)造方法交給線程類來創(chuàng)建線程對象。至于客戶端沒有其他要改動的地方。

客戶端代碼如下:

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1",9999);

        OutputStream os = socket.getOutputStream();
        DataOutputStream dos = new DataOutputStream(os);
        Scanner scanner = new Scanner(System.in);
        while (true){
            System.out.println("請輸入:");
            String str = scanner.nextLine();

            if ("exit".equals(str)){
                System.out.println("退出成功!!!!");
                dos.close();
                socket.close();
                break;
            }
            dos.writeUTF(str);
            //刷新數(shù)據(jù)
            dos.flush();
        }
    }
}

服務(wù)端代碼如下:

繼承 Thread 類:

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

public class ThreadServer extends Thread{
    private final Socket socket ;
    public ThreadServer(Socket socket){
        this.socket = socket;
    }
    @Override
    public void run() {
        try {
            InputStream inputStream = socket.getInputStream();
            DataInputStream dis = new DataInputStream(inputStream);
            while (true){
                try {
                    String str = dis.readUTF();
                    System.out.println(" 來自主機IP為:"+socket.getInetAddress().getHostAddress() +
                            " ,主機名為:" + socket.getInetAddress().getHostName() + ",端口號為:" + socket.getPort() + "發(fā)送的信息:"+str);
                } catch (IOException e) {
                    System.out.println(socket.getRemoteSocketAddress()+" 已下線了 !!!!");
                    dis.close();
                    socket.close();
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

服務(wù)端代碼:

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

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

        while (true){
            Socket socket = serverSocket.accept();
            new ThreadServer(socket).start();
            System.out.println(socket.getRemoteSocketAddress() + " 已上線啦!!!!");
        }

    }
}

????????這就實現(xiàn)了服務(wù)端可以與多個客戶端進行通信了。

? ? ? ? 2.6 實現(xiàn) TCP 網(wǎng)絡(luò)通信(綜合案例:群聊)

? ? ? ? 比如說:微信群聊,客戶端一方發(fā)送了一條消息,不僅當前客戶端可以看到這條消息,其他在群內(nèi)的客戶端也可以看得見這條消息。

? ? ? ? 實現(xiàn)思路:想要實現(xiàn)客戶端發(fā)送的消息,群里的客戶端都可以看見,那么需要將客戶端發(fā)送的這條消息先要發(fā)送給服務(wù)端,再有服務(wù)端分發(fā)給其他群里的客戶端即可。

? ? ? ? 2.6.1 客戶端的開發(fā)

? ? ? ? 對于客戶端來說,既可以有發(fā)送消息的功能,也有接收消息的能力。那么就可以再創(chuàng)建一個線程來負責接收消息。

代碼如下:

繼承 Thread 類:

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

public class ThreadClient extends Thread{
    private Socket socket;
    public ThreadClient(Socket socket){
        this.socket = socket;
    }
    @Override
    public void run() {
        try {
            //開始接收數(shù)據(jù)
            InputStream inputStream = socket.getInputStream();
            DataInputStream dis = new DataInputStream(inputStream);
            while (true){
                try {
                    String str = dis.readUTF();
                    System.out.println( " : " + str);
                } catch (IOException e) {
                    System.out.println(" 本機已離線!!! ");
                    dis.close();
                    socket.close();
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

客戶端代碼:

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1",9999);
        //負責接收消息的線程
        new ThreadClient(socket).start();

        //主線程負責發(fā)送消息
        OutputStream os = socket.getOutputStream();
        DataOutputStream dos = new DataOutputStream(os);
        Scanner scanner = new Scanner(System.in);
        while (true){
            System.out.println("請輸入:");
            String str = scanner.nextLine();
            String sign = "exit";
            if (sign.equals(str)){
                System.out.println("退出成功!!!!");
                dos.close();
                socket.close();
                break;
            }
            dos.writeUTF(str);
            //刷新數(shù)據(jù)
            dos.flush();
        }
    }
}

? ? ? ? 2.6.2 服務(wù)端的開發(fā)

????????首先需要記住群內(nèi)都有哪些客戶端對象,可以用數(shù)組來接收這些客戶端對象,每一個客戶端上線的時候,將該客戶端對象放到數(shù)組容器中。再接收完某一個客戶端發(fā)送的消息后,再將其數(shù)組進行遍歷發(fā)送消息即可。

代碼如下:

繼承 Thread 類:

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

public class ThreadServer extends Thread{
    private Socket socket ;
    public ThreadServer(Socket socket){
        this.socket = socket;
    }
    @Override
    public void run() {
        try {
            InputStream inputStream = socket.getInputStream();
            DataInputStream dis = new DataInputStream(inputStream);
            while (true){
                try {
                    String str = dis.readUTF();
                    System.out.println(" 來自主機IP為:"+socket.getInetAddress().getHostAddress() +
                            " ,主機名為:" + socket.getInetAddress().getHostName() + ",端口號為:" + socket.getPort() + "發(fā)送的信息:"+str);

                    //將消息發(fā)送到每個客戶端中
                    sendClient(str);
                } catch (IOException e) {
                    System.out.println(socket.getRemoteSocketAddress()+" 已下線了 !!!!");
                    Server.socketList.remove(socket);
                    dis.close();
                    socket.close();
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void sendClient(String str) throws IOException {
        for (Socket s : Server.socketList) {
            OutputStream os = s.getOutputStream();
            DataOutputStream dos = new DataOutputStream(os);
            dos.writeUTF(str);
            dos.flush();
        }
    }
}

服務(wù)端代碼:

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class Server {
    public static List<Socket> socketList = new ArrayList<>();
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9999);

        while (true){
            Socket socket = serverSocket.accept();
            new ThreadServer(socket).start();
            socketList.add(socket);
            System.out.println(socket.getRemoteSocketAddress() + " 已上線啦!!!!");
        }

    }
}

運行結(jié)果:

服務(wù)端的運行輸出的結(jié)果:

JavaEE 初階篇-深入了解 UDP 通信與 TCP 通信(綜合案例:實現(xiàn) TCP 通信群聊),JavaEE 初級篇,udp,tcp/ip,網(wǎng)絡(luò),java,java-ee,開發(fā)語言,大數(shù)據(jù)

客戶端 1 運行輸出的結(jié)果:

JavaEE 初階篇-深入了解 UDP 通信與 TCP 通信(綜合案例:實現(xiàn) TCP 通信群聊),JavaEE 初級篇,udp,tcp/ip,網(wǎng)絡(luò),java,java-ee,開發(fā)語言,大數(shù)據(jù)

客戶端 2 運行輸出的結(jié)果:

JavaEE 初階篇-深入了解 UDP 通信與 TCP 通信(綜合案例:實現(xiàn) TCP 通信群聊),JavaEE 初級篇,udp,tcp/ip,網(wǎng)絡(luò),java,java-ee,開發(fā)語言,大數(shù)據(jù)

客戶端 3 運行輸出的結(jié)果:

JavaEE 初階篇-深入了解 UDP 通信與 TCP 通信(綜合案例:實現(xiàn) TCP 通信群聊),JavaEE 初級篇,udp,tcp/ip,網(wǎng)絡(luò),java,java-ee,開發(fā)語言,大數(shù)據(jù)

? ? ? ? 這就是實現(xiàn)了群聊了,一共有三個客戶端,每個客戶端發(fā)消息給服務(wù)器,然后由服務(wù)器再分發(fā)送消息給三個客戶端。如果有某一個客戶端先斷開連接,輸出 "exit" 就可以斷開與服務(wù)器的連接,那么數(shù)組中就會刪除退出的 Socket 對象,其它客戶端不受影響。

? ? ? ? 由于 IP 的限制(IP 為內(nèi)網(wǎng)),不能讓其他的機器連接目前的機器,所以只能本機的程序連接本地的程序。如果 IP 為外網(wǎng),就可以讓其他機器來連接了,實現(xiàn)跨主機通信了。

JavaEE 初階篇-深入了解 UDP 通信與 TCP 通信(綜合案例:實現(xiàn) TCP 通信群聊),JavaEE 初級篇,udp,tcp/ip,網(wǎng)絡(luò),java,java-ee,開發(fā)語言,大數(shù)據(jù)文章來源地址http://www.zghlxwxcb.cn/news/detail-858562.html

到了這里,關(guān)于JavaEE 初階篇-深入了解 UDP 通信與 TCP 通信(綜合案例:實現(xiàn) TCP 通信群聊)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • JavaEE 初階篇-深入了解 I/O 高級流(緩沖流、交換流、數(shù)據(jù)流和序列化流)

    JavaEE 初階篇-深入了解 I/O 高級流(緩沖流、交換流、數(shù)據(jù)流和序列化流)

    ??博客主頁:?【 小扳_-CSDN博客】 ?感謝大家點贊??收藏?評論? 文章目錄 ? ? ? ? 1.0 緩沖流概述 ? ? ? ? 1.1 緩沖流的工作原理 ? ? ? ? 1.2 使用緩沖流的步驟 ? ? ? ? 1.3?字節(jié)緩沖流于字符緩沖流的區(qū)別 ? ? ? ? 1.4?字節(jié)緩沖流的實例 ? ? ? ? 1.5?字符緩沖流的實例

    2024年04月29日
    瀏覽(22)
  • JavaEE 初階篇-生產(chǎn)者與消費者模型(線程通信)

    JavaEE 初階篇-生產(chǎn)者與消費者模型(線程通信)

    ??博客主頁:?【 小扳_-CSDN博客】 ?感謝大家點贊??收藏?評論? ? 文章目錄 ? ? ? ? 1.0 生產(chǎn)者與消費者模型概述 ? ? ? ? 2.0?在生產(chǎn)者與消費者模型中涉及的關(guān)鍵概念 ? ? ? ? 2.1 緩沖區(qū) ? ? ? ? 2.2 生產(chǎn)者 ? ? ? ? 2.3 消費者 ? ? ? ? 2.4 同步機制 ? ? ? ? 2.5 線程間通

    2024年04月28日
    瀏覽(31)
  • JavaEE 初階篇-深入了解 CAS 機制與12種鎖的特征(如樂觀鎖和悲觀鎖、輕量級鎖與重量級鎖、自旋鎖與掛起等待鎖、可重入鎖與不可重入鎖等等)

    JavaEE 初階篇-深入了解 CAS 機制與12種鎖的特征(如樂觀鎖和悲觀鎖、輕量級鎖與重量級鎖、自旋鎖與掛起等待鎖、可重入鎖與不可重入鎖等等)

    ??博客主頁:?【 小扳_-CSDN博客】 ?感謝大家點贊??收藏?評論? 文章目錄 ? ? ? ? 1.0 樂觀鎖與悲觀鎖概述 ? ? ? ? 1.1 悲觀鎖(Pessimistic Locking) ? ? ? ? 1.2 樂觀鎖(Optimistic Locking) ? ? ? ? 1.3 區(qū)別與適用場景 ? ? ? ? 2.0 輕量級鎖與重量級鎖概述 ? ? ? ? 2.1 真正加

    2024年04月16日
    瀏覽(41)
  • JavaEE 初階篇-線程安全的集合類、多線程環(huán)境使用 ArrayList、隊列、哈希表(HashMap 、ConCurrentHashMap 、HashTable 的區(qū)別)

    JavaEE 初階篇-線程安全的集合類、多線程環(huán)境使用 ArrayList、隊列、哈希表(HashMap 、ConCurrentHashMap 、HashTable 的區(qū)別)

    ??博客主頁:?【 小扳_-CSDN博客】 ?感謝大家點贊??收藏?評論? ? 文章目錄 ? ? ? ? 1.0 線程安全的集合類 ? ? ? ? 1.2?線程安全的集合類 - Vector ? ? ? ? 1.3 線程安全的集合類 - Stack ? ? ? ? 1.4 線程安全的集合類 - HashTable ? ? ? ? 2.0 多線程環(huán)境使用 ArrayList ? ? ? ?

    2024年04月25日
    瀏覽(59)
  • 【JavaEE初階】了解JVM

    【JavaEE初階】了解JVM

    JVM啟動的時候,會申請到一整個很大的內(nèi)存區(qū)域.JVM是一個應(yīng)用程序,要從操作系統(tǒng)里申請內(nèi)存.JVM就根據(jù)需要,把空間分為幾個部分,每個部分各自有不同的功能.具體劃分如下: Native Method Stacks(本地方法棧) :native表示是JVM內(nèi)部的C++代碼.就是給調(diào)用native方法(JVM內(nèi)部的方法)準備的???/p>

    2024年02月13日
    瀏覽(25)
  • 了解JVM(JavaEE初階系列19)

    了解JVM(JavaEE初階系列19)

    目錄 前言: 1.JVM是如何運行的 2.JVM中的內(nèi)存區(qū)域劃分 3.JVM的類加載機制 3.1JVM加載機制的五大步驟 3.1.1加載 3.1.1驗證 3.1.1準備 3.1.1解析 3.1.1初始化 3.2總結(jié) 3.3JVM啟動時機 3.4雙親委派模型 4.JVM中的垃圾回收策略 4.1JVM垃圾回收機制概念 4.2垃圾回收策略 4.2.1判斷引用是否有指向 4

    2024年02月10日
    瀏覽(39)
  • 【JavaEE初階】 TCP協(xié)議詳細解析

    【JavaEE初階】 TCP協(xié)議詳細解析

    TCP(Transmission Control Protocol 傳輸控制協(xié)議)是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議。 源/目的端口號:表示數(shù)據(jù)是從哪個進程來,到哪個進程去; 32位序號/32位確認號:后面詳細講; 4位TCP報頭長度:表示該TCP頭部有多少個32位bit(有多少個4字節(jié));所以

    2024年02月05日
    瀏覽(22)
  • 【JavaEE初階】TCP/IP協(xié)議(二)

    【JavaEE初階】TCP/IP協(xié)議(二)

    協(xié)議頭格式如下: 4位版本號(version):指定IP協(xié)議的版本,對于IPv4來說,就是4。IPv6就是6. 4位頭部長度(header length):描述了IP報頭多長。(IP報頭是變長的)報頭中有一個選項部分 是變長的。是可有可無的。 此處的單位也是四字節(jié)。 8位服務(wù)類型(Type Of Service):3位優(yōu)先

    2024年02月12日
    瀏覽(45)
  • 深入了解ESP8266WIFI模塊的工作原理及特點---AT指令詳解---透傳概念----TCP和UDP的特點與區(qū)別-嵌入式軟件面試常問

    深入了解ESP8266WIFI模塊的工作原理及特點---AT指令詳解---透傳概念----TCP和UDP的特點與區(qū)別-嵌入式軟件面試常問

    為什么要拿這個簡單的模塊來講一下呢?因為根據(jù)本人最近嵌入式軟件面試來看,對于我們嵌入式應(yīng)屆,面試官主要問我們簡歷上做過的項目,大多應(yīng)屆生應(yīng)該都接觸過ESP8266或者ESP32吧,他們經(jīng)常會對我們使用過的模塊進行深入的追問,我們很有必要將自己使用過的模塊深入學

    2024年04月27日
    瀏覽(22)
  • 【JavaEE初階】 TCP服務(wù)器與客戶端的搭建

    【JavaEE初階】 TCP服務(wù)器與客戶端的搭建

    TCP服務(wù)器與客戶端的搭建需要借助以下API TCP之間通信通過流進行傳輸,無論是服務(wù)器還是客戶端:讀取內(nèi)容用輸入流,寫入內(nèi)容用輸出流 ServerSocket 是創(chuàng)建TCP服務(wù)端Socket的API。 ServerSocket 構(gòu)造方法 : 方法簽名 方法說明 ServerSocket(int port) 創(chuàng)建一個服務(wù)端流套接字Socket,并綁定

    2024年02月05日
    瀏覽(22)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包