JavaEE 初阶篇-深入了解 UDP 通信与 TCP 通信(综合案例:实现 TCP 通信群聊)

这篇具有很好参考价值的文章主要介绍了JavaEE 初阶篇-深入了解 UDP 通信与 TCP 通信(综合案例:实现 TCP 通信群聊)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

🔥博客主页: 【小扳_-CSDN博客】
❤感谢大家点赞👍收藏⭐评论✍

JavaEE 初阶篇-深入了解 UDP 通信与 TCP 通信(综合案例:实现 TCP 通信群聊),JavaEE 初级篇,udp,tcp/ip,网络,java,java-ee,开发语言,大数据

JavaEE 初阶篇-深入了解 UDP 通信与 TCP 通信(综合案例:实现 TCP 通信群聊),JavaEE 初级篇,udp,tcp/ip,网络,java,java-ee,开发语言,大数据

文章目录

        1.0 UDP 通信

        1.1 DatagramSocket 类

        1.2 DatagramPacket 类

        1.3 实现 UDP 通信(一发一收)

        1.3.1 客户端的开发

        1.3.2 服务端的开发

        1.4 实现 UDP 通信(多发多收)

        1.4.1 客户端的开发

        1.4.2 服务端的开发

        2.0 TCP 网络通信

        2.1 Socket 类

        2.2 ServerSocket 类

        2.3 实现 TCP 网络通信(一发一收)

        2.3.1 客户端的开发

        2.3.2 服务端的开发

        2.4 实现 TCP 网络通信(多发多收)

        2.4.1 客户端的开发

        2.4.2 服务端的开发

        2.5 实现 TCP 网络通信(支持与多个客户端通信)

        2.6 实现 TCP 网络通信(综合案例:群聊)

        2.6.1 客户端的开发

        2.6.2 服务端的开发


        1.0 UDP 通信

        无连接、不可靠通信。

        不事先建立连接;发送端每次把要发送的数据(限制在 64 KB 内)、接收端 IP 等信息封装成一个数据包,发出去就不管了。

        Java 提供了一个 Java.net.DatagramSocket 类来实现 UDP 通信。

        1.1 DatagramSocket 类

        用于创建客户端、服务端。Java 中用于实现 UDP 协议的套接字类,用于创建 UDP 套接字并进行数据传输。UDP 是无连接的、不可靠的传输协议,适用于一些要求实时性较高、容忍少量数据丢失的应用场景。

构造器:

        1)public DatagramSocket():创建客户端的 Socket 对象,系统会随机分配一个端口号。

        2)public DatagramSocket(int port):创建服务端的 Socket 兑现,并指定端口号。

方法:

        1)public void send(DatagramPacket dp):发送数据包。

        2)public void receive(DatagramPacket p):使用数据包接收数据。

        3)public void close():关闭 UDP 套接字。

        1.2 DatagramPacket 类

        创建数据包。用于在 UDP 通信中封装数据和目标地址信息。DatagramPacket 类包含了要发送或接收的数据、数据的长度、目标地址和端口等信息。

构造器:

        1)public DatagramPacket(byte[] buf,int length,InetAddress address,int port):创建发出去的数据包对象。

        2)public DatagramPacket(byte[] buf,int length):创建用来接收的数据的数据包。

方法:

        1)getData():获取数据 数据的字节数组。

        2)getLength():获取数据的长度。字节数组的长度。

        3)getAddress():获取数据报的目标地址。返回的是 InetAddress 类对象,即接收的 IP 对象。

        4)getPort():获取数据报的目标端口。

        1.3 实现 UDP 通信(一发一收)

        整个的过程可以比作:厨师将碟子上的“炒粉”隔空抛出去给服务员(客户端发消息过程),服务员用碟子接收“炒粉”(服务端接收消息过程)。注意的是抛出去的只是“炒粉”,而碟子是不抛出去的。

        1.3.1 客户端的开发

        厨师将碟子上的“炒粉”隔空抛出去给服务员(客户端发消息过程)。

        首先是对客户端的开发,先创建客户端对象,利用无参构造器 DatagramSocket() 来创建一个由系统分配的 IP 地址的客户端对象。把客户端对象可以比作成一个厨师。

        再来创建发出去的数据包对象,利用 DatagramPacket(byte[] buf,int length,InetAddress address,int port) 构造器来创建数据包对象。把数据包对象可以比作厨师手上的碟子,其中参数 buf 是存放数据的容器,把 buf 比如碟子上盛的“炒粉”,参数 length 是用来记录发送数据的大小,参数 address 是发送的 IP 地址对象,将 address 可以比作碟子上的“炒粉”通过 address 来定位到具体要发送的目标服务员。参数 port 是用来记录发送的目标程序即端口号。

代码如下:

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

public class demo1 {
    public static void main(String[] args) throws IOException {
        DatagramSocket socket = new DatagramSocket();
        
        String msg = "需要发送的消息";
        //将字符串转化为字节数组
        byte[] m = msg.getBytes();
        //假如:发送的地方正是本机,就可以通过 InetAddress.getLocalHost() 方法来获取到 IP 地址对象,
        //发送的程序端口号假设为: 8888
        DatagramPacket packet = new DatagramPacket(m,m.length, InetAddress.getLocalHost(),8888);
        //接着就可以发送消息了
        socket.send(packet);
        
        //最后记得要关闭资源
        socket.close();
        
    }
}

        厨师将碟子上的“炒粉”隔空抛出去给服务员,服务员用碟子接收“炒粉”。注意的是抛出去的只是“炒粉”,而碟子是不抛出去的。

        1.3.2 服务端的开发

        服务员用碟子接收“炒粉”(服务端接收消息过程)。

        首先创建服务端对象,利用有参构造器 DatagramSocket(8888) 来创建端口号为 8888 的服务端对象。

        这里用到有参构造器来创建指定的端口号是因为:为了其他客户端精确无误的发送消息到目标程序上。不用无参构造器的是因为:利用无参构造器创建的服务端是由系统随机分配端口号,不利于其他客户端访问服务端。

        接着创建接收数据的数据包对象,利用 DatagramPacket(byte[] buf,int length) 构造器来创建数据包对象,用来接收数据。

        接收完毕之后,需要关闭资源。

代码如下:

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 {
        //创建服务端对象,且指定端口号
        DatagramSocket socket = new DatagramSocket(8888);

        //创建数据包对象
        //接收数据的容器的大小,最大发送过来的数据大小不会超过64KB,
        //因此用64KB大小的字节数组来接收数据
        byte[] bytes = new byte[1024*64];
        DatagramPacket packet = new DatagramPacket(bytes,bytes.length);
        //此时就可以用数据包来接收数据了
        socket.receive(packet);

        //输出数据
        byte[] data = packet.getData();
        //转化为字符串
        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);

        //关闭资源
        socket.close();

    }
}

        1.4 实现 UDP 通信(多发多收)

        客户端可以多次发送消息给服务端,服务端可以多次接收客户端发送的消息。

        1.4.1 客户端的开发

        在以上代码进行改造,对发送消息的代码设置循环。注意退出程序的时候需要关闭资源。

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("请输出需要发送的消息:");
            String msg = scanner.nextLine();
            if ("exit".equals(msg)){
                System.out.println("成功退出!!!");
                //最后记得要关闭
                socket.close();
                break;
            }
            //将字符串转化为字节数组
            byte[] m = msg.getBytes();
            //假如:发送的地方正是本机,就可以通过 InetAddress.getLocalHost() 方法来获取到 IP 地址对象,
            //发送的程序端口号假设为: 8888
            DatagramPacket packet = new DatagramPacket(m,m.length, InetAddress.getLocalHost(),8888);
            //接着就可以发送消息了
            socket.send(packet);
        }
    }
}

        1.4.2 服务端的开发

        设置循环接收消息。其实对于服务端来说,不应该关闭资源,因为随时等待着客户端来访问。

代码如下:

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 {
        //创建服务端对象,且指定端口号
        DatagramSocket socket = new DatagramSocket(8888);

        //创建数据包对象
        //接收数据的容器的大小,最大发送过来的数据大小不会超过64KB,
        //因此用64KB大小的字节数组来接收数据
        byte[] bytes = new byte[1024*64];
        DatagramPacket packet = new DatagramPacket(bytes,bytes.length);


        while (true) {
            //此时就可以用数据包来接收数据了
            socket.receive(packet);

            //输出数据
            byte[] data = packet.getData();
            //转化为字符串
            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("========================");
        }

/*        //关闭资源
        socket.close();*/

    }
}

运行结果:

服务端:

JavaEE 初阶篇-深入了解 UDP 通信与 TCP 通信(综合案例:实现 TCP 通信群聊),JavaEE 初级篇,udp,tcp/ip,网络,java,java-ee,开发语言,大数据

客户端:

JavaEE 初阶篇-深入了解 UDP 通信与 TCP 通信(综合案例:实现 TCP 通信群聊),JavaEE 初级篇,udp,tcp/ip,网络,java,java-ee,开发语言,大数据

        需要注意的是:在启动程序的时候,应该先启动服务端程序,再启动客户端程序。

        2.0 TCP 网络通信

        面向连接、可靠连接。

        2.1 Socket 类

        Java 中用于实现 TCP 通信的类,主要用于在客户端和服务器之间建立 TCP 连接。通过 Socket 类,可以在客户端和服务器之间进行双向通信,实现数据的传输和交互。

        1)创建 Socket 对象:通过 Socket 类的构造方法可以创建一个 Socket 对象,用于表示客户端与服务器之间的 TCP 连接。可以连接指定的服务器和端口。

        2)发送数据:通过 Socket 类的 getOutputStream 方法获取输出流,可以向服务器发送数据。

        3)接收数据:通过 Socket 类的 getInputStream 方法获取输入流,可以从服务器接收数据。

        4)关闭连接:通过 Socket 类的 close 方法可以关闭 TCP 连接。

其他常用的方法:

        1)getInetAddress() 方法:获取远程主机的地址,返回 InetAddress 对象。

        2)getPort() 方法:获取远程主机的端口号。

        3)getLocalAddress() 方法:获取本地主机的地址,返回 InetAddress 对象。

        4)getLocalPort() 方法:获取本地主机的端口号。

        简单来说,通过构造方法指定的 IP 地址和端口号来创建的客户端与指定的服务器建立连接。建立连接相当于创建了管道。创建管道来支持字节流的发送或者接收。通过 getOutputStream 方法或者 getInputStream 方法来发送或者接收字节流。

        2.2 ServerSocket 类

        Java 中用于实现 TCP 服务器端的类,它用于监听客户端的连接请求并创建对应的 Socket 对象进行通信。

构造方法:

        ServerSocket(int port) 构造方法:创建一个新的 ServerSocket 对象,绑定到指定的端口。

常用的方法:

        1)accept() 方法:监听并接受客户端的连接请求,返回一个新的 Socket 对象用于与客户端通信。

        2)close() 方法:关闭 ServerSocket 对象,停止监听新的连接请求。

        3)getInetAddress() 方法:获取 ServerSocket 绑定的本地地址。

        4)getLocalPort() 方法:获取 ServerSocket 绑定的本地端口号。

        ServerSocket 类用于在服务器端监听客户端的连接请求,并创建对应的 Socket 对象用于与客户端进行通信。通过 ServerSocket 类提供的方法,您可以管理服务器端的 TCP 连接、设置相关参数以及处理客户端的连接请求。类用于在服务器端监听客户端的连接请求,并创建对应的 Socket 对象用于与客户端进行通信。通过 ServerSocket 类提供的方法,您可以管理服务器端的 TCP 连接、设置相关参数以及处理客户端的连接请求。

        2.3 实现 TCP 网络通信(一发一收)

        2.3.1 客户端的开发

        先创建管道对象,利用有参构造器 Socket(String host,int port) 创建连接指定的服务器的管道。接着,利用 Socket 对象提供的方法 getOutputStream() 方法来获取字节输出流对象,利用该对象进行写操作,最后发送完毕之后,需要关闭资源。

代码如下:

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

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

        //获取到输出流
        OutputStream os = socket.getOutputStream();
        //将其低级的输出流升级为高级的输出流
        DataOutputStream dos = new DataOutputStream(os);

        dos.writeUTF("需要发送的消息!!!");

        //关闭资源
        dos.close();
        socket.close();

    }
}

        注意关闭资源的顺序,先关闭后开启的资源,再关闭前面开启的资源

        2.3.2 服务端的开发

        先创建 ServerSocket 类,用有参构造器 ServerSocket(int port) 创建指定端口号的对象,再用 accept() 方法来等待接收来自客户端发送来的连接请求,客户端与服务端连接完毕之后,就会返回一个 Socket 对象给服务端,该 Socket 对象可以理解为管道的服务器的一端,客户端已经有 Socket 对象了,该对象就可以理解为管道的客户端的一端。

        接着,通过 Socket 提供的方法来获取二进制输出流对象或者是二进制输入流对象,通过管道将数据进行传输到客户端。

代码如下:

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(8888);

        //等待客户端发送消息来获取管道对象
        Socket socket = serverSocket.accept();
        //通过管道对象再来获取到读取流对象
        InputStream inputStream = socket.getInputStream();
        //再将低级流转化为高级流
        DataInputStream dis = new DataInputStream(inputStream);
        String s = dis.readUTF();
        System.out.println(s);

        //关闭资源
        dis.close();
        socket.close();

    }
}

运行结果:

JavaEE 初阶篇-深入了解 UDP 通信与 TCP 通信(综合案例:实现 TCP 通信群聊),JavaEE 初级篇,udp,tcp/ip,网络,java,java-ee,开发语言,大数据

        客户端发送数据,服务端接收数据的代码就实现了。

        2.4 实现 TCP 网络通信(多发多收)

        2.4.1 客户端的开发

        将以上客户端的代码输出数据进行循环即可,每次输出完数据之后,最好刷新一下。

代码如下:

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

public class MyClient {
    //TCP 实现多发多收
    public static void main(String[] args) throws IOException {
        //创建管道对象
        Socket socket = new Socket("127.0.0.1",8888);
        //获取写数据流
        OutputStream os = socket.getOutputStream();
        //将低级流转换为高级流
        DataOutputStream dos = new DataOutputStream(os);
        Scanner scanner = new Scanner(System.in);

        while (true) {
            String msg = scanner.nextLine();
            if ("exit".equals(msg)){
                System.out.println("退出成功!!!!");
                //关闭资源
                dos.close();
                socket.close();
                break;
            }
            //写数据
            dos.writeUTF(msg);
            //刷新数据,将缓存的数据进行刷新
            dos.flush();
        }
    }
}

        2.4.2 服务端的开发

        将以上服务端的输入数据的代码加上循环即可,需要注意的是:在客户端管道一端假设要断开连接的时候,此时服务端还在连接着管道,这就会导致服务端一端会报异常,因此,需要对服务端输入数据这一段代码加上 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 {
        //创建服务端管道对象
        ServerSocket serverSocket = new ServerSocket(8888);

        //等待接收客户端,创建管道对象
        Socket socket = serverSocket.accept();
        //创建完管道之后,就要创建字节流
        InputStream inputStream = socket.getInputStream();
        //再将低级流升级为高级流
        DataInputStream dis = new DataInputStream(inputStream);

        while (true) {
            try {
                //接着就可以读数据了
                String s = dis.readUTF();
                System.out.println(s);
                //通过管道对象来获取到发送消息的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 实现 TCP 网络通信(支持与多个客户端通信)

        实现思路:当前服务端只有主线程负责一个客户端进行通信,那么实现服务端与多个客户端实现通信需要实现多线程,在服务端中创建多个线程,每一个线程都对应一个客户端进行通信,而主线线程将将接收到的 Socket 对象通过构造方法交给线程类来创建线程对象。至于客户端没有其他要改动的地方。

客户端代码如下:

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);
            //刷新数据
            dos.flush();
        }
    }
}

服务端代码如下:

继承 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() + "发送的信息:"+str);
                } catch (IOException e) {
                    System.out.println(socket.getRemoteSocketAddress()+" 已下线了 !!!!");
                    dis.close();
                    socket.close();
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

服务端代码:

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() + " 已上线啦!!!!");
        }

    }
}

        这就实现了服务端可以与多个客户端进行通信了。

        2.6 实现 TCP 网络通信(综合案例:群聊)

        比如说:微信群聊,客户端一方发送了一条消息,不仅当前客户端可以看到这条消息,其他在群内的客户端也可以看得见这条消息。

        实现思路:想要实现客户端发送的消息,群里的客户端都可以看见,那么需要将客户端发送的这条消息先要发送给服务端,再有服务端分发给其他群里的客户端即可。

        2.6.1 客户端的开发

        对于客户端来说,既可以有发送消息的功能,也有接收消息的能力。那么就可以再创建一个线程来负责接收消息。

代码如下:

继承 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 {
            //开始接收数据
            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();

        //主线程负责发送消息
        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);
            //刷新数据
            dos.flush();
        }
    }
}

        2.6.2 服务端的开发

        首先需要记住群内都有哪些客户端对象,可以用数组来接收这些客户端对象,每一个客户端上线的时候,将该客户端对象放到数组容器中。再接收完某一个客户端发送的消息后,再将其数组进行遍历发送消息即可。

代码如下:

继承 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() + "发送的信息:"+str);

                    //将消息发送到每个客户端中
                    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();
        }
    }
}

服务端代码:

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() + " 已上线啦!!!!");
        }

    }
}

运行结果:

服务端的运行输出的结果:

JavaEE 初阶篇-深入了解 UDP 通信与 TCP 通信(综合案例:实现 TCP 通信群聊),JavaEE 初级篇,udp,tcp/ip,网络,java,java-ee,开发语言,大数据

客户端 1 运行输出的结果:

JavaEE 初阶篇-深入了解 UDP 通信与 TCP 通信(综合案例:实现 TCP 通信群聊),JavaEE 初级篇,udp,tcp/ip,网络,java,java-ee,开发语言,大数据

客户端 2 运行输出的结果:

JavaEE 初阶篇-深入了解 UDP 通信与 TCP 通信(综合案例:实现 TCP 通信群聊),JavaEE 初级篇,udp,tcp/ip,网络,java,java-ee,开发语言,大数据

客户端 3 运行输出的结果:

JavaEE 初阶篇-深入了解 UDP 通信与 TCP 通信(综合案例:实现 TCP 通信群聊),JavaEE 初级篇,udp,tcp/ip,网络,java,java-ee,开发语言,大数据

        这就是实现了群聊了,一共有三个客户端,每个客户端发消息给服务器,然后由服务器再分发送消息给三个客户端。如果有某一个客户端先断开连接,输出 "exit" 就可以断开与服务器的连接,那么数组中就会删除退出的 Socket 对象,其它客户端不受影响。

        由于 IP 的限制(IP 为内网),不能让其他的机器连接目前的机器,所以只能本机的程序连接本地的程序。如果 IP 为外网,就可以让其他机器来连接了,实现跨主机通信了。

JavaEE 初阶篇-深入了解 UDP 通信与 TCP 通信(综合案例:实现 TCP 通信群聊),JavaEE 初级篇,udp,tcp/ip,网络,java,java-ee,开发语言,大数据文章来源地址https://www.toymoban.com/news/detail-858562.html

到了这里,关于JavaEE 初阶篇-深入了解 UDP 通信与 TCP 通信(综合案例:实现 TCP 通信群聊)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JavaEE 初阶篇-深入了解 I/O 高级流(缓冲流、交换流、数据流和序列化流)

    🔥博客主页: 【 小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录         1.0 缓冲流概述         1.1 缓冲流的工作原理         1.2 使用缓冲流的步骤         1.3 字节缓冲流于字符缓冲流的区别         1.4 字节缓冲流的实例         1.5 字符缓冲流的实例

    2024年04月29日
    浏览(39)
  • JavaEE 初阶篇-生产者与消费者模型(线程通信)

    🔥博客主页: 【 小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍   文章目录         1.0 生产者与消费者模型概述         2.0 在生产者与消费者模型中涉及的关键概念         2.1 缓冲区         2.2 生产者         2.3 消费者         2.4 同步机制         2.5 线程间通

    2024年04月28日
    浏览(32)
  • JavaEE 初阶篇-深入了解 CAS 机制与12种锁的特征(如乐观锁和悲观锁、轻量级锁与重量级锁、自旋锁与挂起等待锁、可重入锁与不可重入锁等等)

    🔥博客主页: 【 小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录         1.0 乐观锁与悲观锁概述         1.1 悲观锁(Pessimistic Locking)         1.2 乐观锁(Optimistic Locking)         1.3 区别与适用场景         2.0 轻量级锁与重量级锁概述         2.1 真正加

    2024年04月16日
    浏览(26)
  • JavaEE 初阶篇-线程安全的集合类、多线程环境使用 ArrayList、队列、哈希表(HashMap 、ConCurrentHashMap 、HashTable 的区别)

    🔥博客主页: 【 小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍   文章目录         1.0 线程安全的集合类         1.2 线程安全的集合类 - Vector         1.3 线程安全的集合类 - Stack         1.4 线程安全的集合类 - HashTable         2.0 多线程环境使用 ArrayList        

    2024年04月25日
    浏览(39)
  • 【JavaEE初阶】了解JVM

    JVM启动的时候,会申请到一整个很大的内存区域.JVM是一个应用程序,要从操作系统里申请内存.JVM就根据需要,把空间分为几个部分,每个部分各自有不同的功能.具体划分如下: Native Method Stacks(本地方法栈) :native表示是JVM内部的C++代码.就是给调用native方法(JVM内部的方法)准备的栈空

    2024年02月13日
    浏览(44)
  • 了解JVM(JavaEE初阶系列19)

    目录 前言: 1.JVM是如何运行的 2.JVM中的内存区域划分 3.JVM的类加载机制 3.1JVM加载机制的五大步骤 3.1.1加载 3.1.1验证 3.1.1准备 3.1.1解析 3.1.1初始化 3.2总结 3.3JVM启动时机 3.4双亲委派模型 4.JVM中的垃圾回收策略 4.1JVM垃圾回收机制概念 4.2垃圾回收策略 4.2.1判断引用是否有指向 4

    2024年02月10日
    浏览(27)
  • 【JavaEE初阶】 TCP协议详细解析

    TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。 源/目的端口号:表示数据是从哪个进程来,到哪个进程去; 32位序号/32位确认号:后面详细讲; 4位TCP报头长度:表示该TCP头部有多少个32位bit(有多少个4字节);所以

    2024年02月05日
    浏览(24)
  • 【JavaEE初阶】TCP/IP协议(二)

    协议头格式如下: 4位版本号(version):指定IP协议的版本,对于IPv4来说,就是4。IPv6就是6. 4位头部长度(header length):描述了IP报头多长。(IP报头是变长的)报头中有一个选项部分 是变长的。是可有可无的。 此处的单位也是四字节。 8位服务类型(Type Of Service):3位优先

    2024年02月12日
    浏览(28)
  • 深入了解ESP8266WIFI模块的工作原理及特点---AT指令详解---透传概念----TCP和UDP的特点与区别-嵌入式软件面试常问

    为什么要拿这个简单的模块来讲一下呢?因为根据本人最近嵌入式软件面试来看,对于我们嵌入式应届,面试官主要问我们简历上做过的项目,大多应届生应该都接触过ESP8266或者ESP32吧,他们经常会对我们使用过的模块进行深入的追问,我们很有必要将自己使用过的模块深入学

    2024年04月27日
    浏览(32)
  • 【JavaEE初阶】万字详解TCP/IP协议!!!(一)

    在网络通信过程中,应用层描述了应用程序如何理解和使用网络中的通信数据。 而程序猿在应用层这里最主要的工作就是自定义协议,自定义协议主要做两件事: 结合业务场景和需求,明确协议数据要传递哪些信息。 明确数据组织格式。(比如:可以按照纯文本方式,也可

    2024年02月07日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包