检查服务器是否已关闭UDP和DatagramChannel Java

时间:2020-05-29 11:28:03

标签: java multithreading sockets udp

因此,我正在开发一个多线程,它将多条命令(命令设计模式)从客户端发送到服务器,然后在那里执行它们并将响应发送回去。

客户端使用java.nio.channels.DatagramChannel通过UDP发送和接收。

在主线程中,我有一个while(true)读取客户端编写的命令并将其发送到服务器,然后进行处理(db请求,文件更改等)并发送回响应,在始终处于活动状态的线程中等待响应。

该系统可以正常工作,直到服务器关闭(如UDP)为止,“不可能”知道服务器何时处于活动,就绪,启动等状态。因此,我尝试确定服务器是否处于“关闭”状态那就是说,如果在发送请求的一秒钟后没有答案,则客户端部分将进入无限循环,该循环每2秒“尝试”连接一次,并发送命令“ connect”直到收到肯定的响应。

由于必须将接收器线程与主线程分开使用,所以我无法在发送请求后一秒钟准确地计算出请求,因为它是分开运行的,也许必须有一种方法可以使主线程响应,如果超过一秒钟,那么他应该像我之前说的那样重试连接。我读到Thread有一些wait() notify()方法可能会帮助我,但是我不确定在我的情况下如何使用它们。代码是向下的。

ClientMain.java

while(true) {
    if (channel.isConnected())
        reader.startInteraction(currentUser.getCredentials());
    else
        channel.tryToConnect(address);

    responseHandler.checkForResponse();
}

ClientResponseHandler.java,此类具有接收方线程作为内部类

public void checkForResponse() {
        startRequestTime = System.currentTimeMillis();

        Object received = receiverThread.receivedObject;

        if (received instanceof String && received.equals("connect")) {
            channel.setConnected(true);
            System.out.println("Successfully connected to the server");
        }

        synchronized (this) {
            if (received != null) {
                flagReceived = true;
                printResponse(received);
            } else {
                flagReceived = false;
            }
            receiverThread.receivedObject = null;
        }
    }

在ReceiverThread.java中,receivedObject是Thread类内部的易失对象

...
protected volatile Object receivedObject = null;
...

public void run() {
    while(true)
        receiveData();
}

public void receiveData() throws IOException, ClassNotFoundException {
            synchronized (ClientResponseHandler.class) {
                //[MARKET]condition that doesn't work protertly
                if (channel.requestWasSent() && !flagReceived && System.currentTimeMillis() - startRequestTime > 1000) {
                    channel.setConnectionToFalse();
                }
            }

            final ByteBuffer buf = ByteBuffer.allocate(AbsUdpSocket.DATA_SIZE);
            final SocketAddress addressFromServer = channel.receiveDatagram(buf);
            buf.flip();

            byte[] bytes = new byte[buf.remaining()];
            buf.get(bytes);

            if (bytes.length < 1)
                return;

            synchronized (ClientResponseHandler.class) {
                channel.setRequestSent(false);
                if (bytes.length < AbsUdpSocket.DATA_SIZE)
                    receivedObject = processResponse(bytes);
                else
                    throw new EOFException();
            }
        }

//The processResponse() is just to convert the received bytes to the needed object

标记的情况是应该重新连接我的代码的魔术,但不起作用。有时,他会在成功请求后重新连接,或者在客户端启动且服务器始终处于启动状态时尝试连接3-4次。并且只有在服务器关闭时才尝试第二次执行命令后重新连接。

0 个答案:

没有答案