为了账号安全,请及时绑定邮箱和手机立即绑定

在单独的线程上获取套接字数据,然后将其传递给主线程

在单独的线程上获取套接字数据,然后将其传递给主线程

慕雪6442864 2021-12-18 15:12:01
编辑了我的问题以进行澄清和代码:我的目标是将我的字符串数据从我的后台线程传递到我的主应用程序线程。任何帮助表示赞赏。这是创建主后台线程的代码。这位于我的 Server.java 类中public class Server {boolean isConnected = false;Controller controller = new Controller();public void startHost() {    Thread host = new Thread(() -> {        Controller controller = new Controller();        ServerSocket server = null;        try {            server = new ServerSocket(GeneralConstants.applicationPort);        } catch (BindException e2) {            System.out.println("Port Already in Use!");        } catch (IOException e) {            //do nothing        }        while (true) {            if (server == null) { break; }            try {                Socket client = server.accept();                System.out.println("Client Connected: " + isConnected);                if (!isConnected) {                    controller.createClientHandler(client);                    isConnected = true;                    System.out.println("Client Connected: " + isConnected);                }            } catch (IOException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }    });    host.setDaemon(true);    host.start();}下面是连接客户端时调用的代码,位于我的 Controller.java 类中。    public synchronized void createClientHandler(Socket client) {    boolean alreadyConnected = false;    if (alreadyConnected) {        //do NOT assign multiple threads for each client    } else {        ClientHandler handleClients = new ClientHandler("client", client);    }}然后该程序为我的客户端创建了两个后台线程,一个用于管理接收消息和发送消息。public ClientHandler(String name, Socket s) {    clientSocket = s;    clientName = name;    receiveThread = new Thread(this::receive);    sendThread = new Thread(this::send);    connected = clientSocket.isConnected();    receiveThread.start();    sendThread.start();}如何从主线程访问我的字符串数据而不会为空?
查看完整描述

1 回答

?
慕标5832272

TA贡献1966条经验 获得超4个赞

开始考虑设计。在网络应用程序中,您通常必须管理以下职责:

  1. 已连接的客户端及其状态(连接状态、心跳……)

  2. 收到客户的消息

  3. 发送给客户端的消息

将这些职责分开以保持代码干净、可读和可维护是有意义的。

分离可以意味着线程和类。

例如,您可以按如下方式实现它:

该类ClientAcceptor负责打开套接字并接受客户端。一旦客户端连接,它将进一步的工作委托给控制器,然后等待其他客户端:

public class ClientAcceptor implements Runnable {


    @Override

    public void run() {

        while (true) {

            ServerSocket server;

            try {

                server = new ServerSocket(1992);

                Socket client = server.accept();


                if (client.isConnected()) {

                    controller.createClientHandler(client);

                }

            } catch (IOException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            }

        }

    }

}

然后控制器可以创建一个处理程序(如果控制器决定这样做,例如它也可以拒绝客户端)。本ClientHandler类可以如下所示:


public class ClientHandler {

    private Thread receiveThread;

    private Thread sendThread;

    private boolean connected;

    private Socket clientSocket;

    private String clientName;

    private LinkedBlockingDeque<byte[]> sendQueue;


    public ClientHandler(String name, Socket s) {

        clientSocket = s;

        clientName = name;


        receiveThread = new Thread(() -> receive());

        sendThread = new Thread(() -> send());


        connected = clientSocket.isConnected();


        receiveThread.start();

        sendThread.start();

    }


    private void receive() {

        BufferedInputStream in = null;

        try {

            in = new BufferedInputStream(clientSocket.getInputStream());

        } catch (IOException e) {

            connected = false;

        }

        while (connected) {

            try {

                byte[] bytes = in.readAllBytes();

                if (bytes != null && bytes.length > 0) {

                    controller.handleReceivedPacket(clientName, bytes);

                }

            } catch (IOException e) {

                e.printStackTrace();

            }

        }

    }


    private void send() {

        BufferedOutputStream out = null;

        try {

            out = new BufferedOutputStream(clientSocket.getOutputStream());

        } catch (IOException e) {

            connected = false;

        }

        while (connected) {

            byte[] toSend = sendQueue.getFirst();

            if (toSend != null && toSend.length > 0) {

                try {

                    out.write(toSend);

                } catch (IOException e) {

                    e.printStackTrace();

                }

            }

        }

    }


    public void send(byte[] packet) {

        sendQueue.add(packet);

    }


    public void close() {

        connected = false;

    }

}

该ClientHandler负责接收和发射数据。如果数据包到达,它会通知控制器,控制器会解析数据包。的ClientHandler还提供了一个公共API来发送数据(其被存储在队列中,并通过一个线程来处理),并关闭连接。


上面的代码示例既未经测试,也不完整。以它为起点。


查看完整回答
反对 回复 2021-12-18
  • 1 回答
  • 0 关注
  • 180 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号