网络编程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);
        }
    }
}

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

相关推荐
啊阿狸不会拉杆7 小时前
《计算机网络-自顶向下方法》5.4 ISP之间的路由选择:BGP 读书笔记
网络·计算机网络·接口隔离原则
phltxy7 小时前
C语言操作符详解
java·c语言·算法
步行cgn8 小时前
@Configuration 详解:Spring 配置类的核心注解
java·后端·spring
sunshine22 girl8 小时前
Java学习一 环境配置2 安装和基本使用Idea
java·学习·intellij-idea
Delite8028 小时前
摆脱实验室束缚:便携式卡尔费休微量水分检测技术与现场应用解析
大数据·网络·人工智能
ACP广源盛139246256739 小时前
M6/M5 Pro Mac mini 端侧 AI 落地@ACP#YLB3116 中端多盘存储扩展在 AI 服务中的机会与应用场景
大数据·网络·数据库·人工智能·嵌入式硬件·macos
ACP广源盛139246256739 小时前
M6/M5 Pro Mac mini 端侧 AI 新形态@ACP#GSV5800 Serdes 长距离视频传输在 AI 服务中的机会与落地场景
大数据·网络·数据库·人工智能·嵌入式硬件·macos·音视频
嘿嘿-6610 小时前
Windows 一键使用 GPT-6 Astra:Codex CLI 配置教程
java·人工智能·windows·gpt·chatgpt·web
我爱cope10 小时前
【计算机网络 | 传输层3:TCP 协议概述:面向连接、可靠传输到底意味着什么?】
网络·网络协议·学习·tcp/ip·计算机网络·传输层
OIDCAT11 小时前
国产USB转千兆网卡芯片CH398-RTL8153国产替代实测与选型
网络·嵌入式硬件·智能硬件·国产芯片·usb转千兆网卡