网络编程5

TCP通信-群聊

Server

java 复制代码
package TCP3;

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

public class Server{
    public static List<Socket> OnlineSockets = new ArrayList<>();
    public static void main(String[] args) throws Exception{
        System.out.println("...服务端启动成功...");

        //1.创建ServerSocket的对象,同时为服务端注册端口
        ServerSocket serverSocket = new ServerSocket(8888);



        while (true) {
            //2.使用serverSocket对象,调用一个accept方法,等待客户端连接请求
            Socket socket = serverSocket.accept();

            //添加在线Socket
            OnlineSockets.add(socket);

            //追踪客户端上限
            System.out.println("有人上线了:"+ socket.getRemoteSocketAddress());

            //3.把这个客户端对应的socket通信管道,交给一个独立的线程负责处理
            new ServerReaderTread(socket).start();
        }
    }
}

创建服务端及其端口后,使用死循环与多个客户端链接,然后再分配子进程去管理这个客户端发来的消息

ServerReadTread

java 复制代码
package TCP3;

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

public class ServerReaderTread extends Thread {

    //线程变量
    private Socket socket;

    //有参构造器
    public ServerReaderTread(Socket socket){
        this.socket = socket;
    }

    public void run(){
        //从socket通信管理中得到一个字节输入流
        try {
            InputStream is = socket.getInputStream();
            DataInputStream dis = new DataInputStream(is);
            while (true){
                try {
                    String msg = dis.readUTF();
                    System.out.println(msg);
                    //把这个消息发给全部客户端进行接收
                    sendMsgToAll(msg);
                } catch (IOException e) {
                    System.out.println("有人下线了:"+ socket.getRemoteSocketAddress());
                    //在在线Socket集合中删除对应端口
                    Server.OnlineSockets.remove(socket);
                    dis.close();
                    socket.close();
                    break;
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private void sendMsgToAll(String msg) throws IOException {
        //发送给全部在线的socket管道接收
        for (Socket onlineSocket : Server.OnlineSockets) {
            OutputStream os = onlineSocket.getOutputStream();
            DataOutputStream dos = new DataOutputStream(os);
            dos.writeUTF(msg);
            dos.flush();

        }
    }
}

客户端每与服务端连接,就会生成这个对应的子进程来管理,将输入字节流转换为数据流后,将其打印,跟踪客户端是否下线,最后将消息转发给所有在线的socket管道

Client

java 复制代码
package TCP3;

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

public class Client{
    public static  void main(String[] args) throws Exception{
        //1.创建Socket对象,并同时请求与服务端的连接
        Socket socket = new Socket("127.0.0.1",8888);

        //创建一个独立的线程,负责随机从socket中接收服务端发送过来的消息
        new ClientReaderTread(socket).start();

        //2.从socket通信管道中得到一个字节输出流,用来发数据给服务端程序
        OutputStream os = socket.getOutputStream();

        //3.把低级的字节输出流包装成数据输出流
        DataOutputStream dos = new DataOutputStream(os);

        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println();
            String msg = sc.nextLine();

            //一旦用户输入了exit,就退出客户端程序
            if("exit".equals(msg)){

                System.out.println("已成功退出");
                dos.close();
                socket.close();
                break;
            }

            //4.开始写数据出去了
            dos.writeUTF(msg);
            dos.flush();
        }
    }

}

创建客户端后,创建对应的客户端子进程用来接收信息,使用死循环不断将信息发送,

ClientReaderTread

java 复制代码
package TCP3;

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

public class ClientReaderTread extends Thread {
    //线程变量
    private Socket socket;

    //有参构造器
    public ClientReaderTread(Socket socket){
        this.socket = socket;
    }
    public void run(){
        try {
            InputStream is = socket.getInputStream();
            DataInputStream dis = new DataInputStream(is);
            while (true){
                try {
                    String msg = dis.readUTF();
                    System.out.println(msg);
                } catch (IOException e) {
                    System.out.println("自己下线了:"+ socket.getRemoteSocketAddress());
                    dis.close();
                    socket.close();
                    break;
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

也是从通信管道中获取这个信息输入流,然后将其打印出来

相关推荐
小比特_蓝光25 分钟前
网络基础篇
网络
盟接之桥1 小时前
线束数字化--先进先出为什么总是停留在纸面上?
大数据·网络·数据库·人工智能·制造·ai编程
FYKJ_20101 小时前
springboot助农产品销售商城05829-计算机课程设计、毕业设计
java·spring boot·python·mysql·spark·django
aixingkong9213 小时前
Nvidia为例 XPU的Multi-Host、Socket Direct 、GPUDirect、RDMA 技术点分析
服务器·网络·硬件架构·硬件工程
user_admin_god4 小时前
第 10 篇:拼上下文与生成——预算、边界与防幻觉
java·人工智能·spring boot·语言模型
用户3126874877204 小时前
GC 算法与垃圾收集器演进:从 Serial 到 ZGC
java
天天被压力4 小时前
【别再到处找免费股票数据API了:官方204个接口,32篇一次讲透 #02】涨停跌停与特色股池:5类股池接口一次拉全
java·人工智能·python
斯维赤4 小时前
从 @Tool 到 Agent 流水线:LangChain4j 进阶教学,一个库打全套
java·后端
SimonKing4 小时前
SSE项目`nexus-sse`持续优化,不一样的视觉效果
java·后端·程序员
斑鸠喳喳4 小时前
读写锁模式 Read-Write Lock
java·后端