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

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

相关推荐
猿究院_夏燊9 小时前
Spring Bean 生命周期
java·后端·spring
Wang's Blog9 小时前
Java 项目实战: 交友项目:登录链路回顾与今日任务地图
java·开发语言·状态模式·交友
Chenyu_3109 小时前
DPDK、TC 和 XDP:Linux 高性能网络到底在优化什么
linux·服务器·网络·缓存
信誓旦旦的程序猿10 小时前
【Python量化实战宝典 #08】可转债与债券接口手册:转股价·溢价率·纯债价值(Python 可跑)
java·python·股票数据api·股票数据api接口·股票api数据接口·股票量化数据api·股票量化数据接口
砚底藏山河10 小时前
python量化:行情数据回溯
java·开发语言·python·金融·maven
Jlzn888810 小时前
华东电芯分选通道数怎么配才不堵线
java·人工智能·架构·自动化·制造
徐同保10 小时前
免费ssl证书全流程AI配置(含七牛云cdn)
网络·网络协议·ssl
香吧香10 小时前
GRPC连接机制---长连接分析
java·网络与传输协议
lisw0510 小时前
制造业信息化:现代工业的发展趋势!
大数据·网络·人工智能
我是人✓10 小时前
SpringBoot项目的五种创建方式
java·spring boot·后端