怎么问天命还活着?

How do i ask the destiny is still alive?

我正在尝试创建两个应用程序之间的消息监视器。这个想法是这个监视器在简单的 client/server 应用程序中间工作,并将消息记录到标准输出。该程序必须防止 client/server 失败(断开连接、超时等)。在代码中,我将客户端称为 "origin",将服务器称为 "destiny"。问题是如果服务器在第一次成功连接后就死了,我不知道怎么问命运还活着? (请参阅代码中的捕获异常)。我执行下一步的:

1.- 我启动 client/server 应用程序

2.- 我开始我的程序(使用线程)

3.- 我从客户端向我的程序发送一条消息,我的程序将此消息传递给服务器,服务器响应我的程序,我的程序成功地将消息传递回客户端。

4.- 现在,我终止并重新启动 client/server 应用程序(不重新启动我的程序)

5.- 我重复步骤“3”,但此时,当程序到达 "len_message_from_destiny = streamFromDestiny.read(buffer_msg_destiny);" 时,它会产生我需要编码的捕获,询问服务器是否真的存在(这是真的在此步骤中)”。在这种情况下尝试读取会生成一个 "SocketException",其描述如下:"Software caused connection abort: recv failed java mail".

如果我放入 catch 代码,我需要再次连接套接字和新流的所有指令,也不起作用。

package interceptorprocess;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;


public class GenericInterceptorProcess implements Runnable
{
private final String prefix_log_messages;
public GenericInterceptorProcessConfigurations confs;

//COMMUNICATION'S ORIGIN'S VARIABLES
ServerSocket serverSocketLocal;
Socket socketForLocal;
DataInputStream streamFromOrigin;
DataOutputStream streamToOrigen;
int len_message_from_origen;
byte[] buffer_msg_origin = new byte[4096];
byte[] message_origin = null;

//COMMUNICATION'S DESTINY'S VARIABLES
Socket socketToDestiny;
DataInputStream streamFromDestiny;
DataOutputStream streamToDestiny;
int len_message_from_destiny;
byte[] buffer_msg_destiny = new byte[4096];
byte[] message_destiny;

GenericInterceptorProcess(GenericInterceptorProcessConfigurations confs_p)
{
    confs = confs_p;
    prefix_log_messages = confs.prefix_log_messages; 
}

@Override
public void run() 
{
    //OCCASIONAL USE
    String aux;

    try
    {
        logger("STARTING SERVER --- PORT NUMBER: " + confs.local_port);

        //CREATING THE LOCAL SERVER SOCKET
        serverSocketLocal = new ServerSocket(confs.local_port);

        //THIS LOOP MAINTAINS THE CONNECTIVITY WITH ONE CLIENT AT TIME
        while ( true )
        {
            //CONNECTION TO THE ORIGIN
            logger("WAITING FOR A CONNECTION OF A CLIENT...");
            socketForLocal = serverSocketLocal.accept();

            streamFromOrigin = new DataInputStream(socketForLocal.getInputStream());
            streamToOrigen = new DataOutputStream(socketForLocal.getOutputStream());

            logger("CONNECTED CLIENT: " + socketForLocal.getRemoteSocketAddress() );

            //CONNECTION TO THE DESTINY
            try
            {
                socketToDestiny = new Socket();
                socketToDestiny.setSoTimeout(confs.timeout_destiny);
                socketToDestiny.connect(new InetSocketAddress(confs.destiny_ip,confs.destiny_port),confs.timeout_connections);

                //CREATING THE DESTINY'S STREAMS
                streamFromDestiny = new DataInputStream(socketToDestiny.getInputStream());
                streamToDestiny = new DataOutputStream(socketToDestiny.getOutputStream()); 
            }
            catch(IOException ex)
            {
                logger("CONNECTION REJECTED BY DESTINY: " + ex.getMessage());
                closeOriginStream();
                continue;
            }

            logger("CONNECTED DESTINY: " + socketToDestiny.getRemoteSocketAddress() );

            //THIS LOOP MAINTAINS THE MESSAGES'S CHANGES
            while ( true )
            {
                logger("WAITING FOR A MESSAGE..");

                //THIS TRY/CATCH EXITS FOR CONNECTION RESETS
                try
                {
                    len_message_from_origen = streamFromOrigin.read(buffer_msg_origin);
                }
                catch(SocketException ex)
                {
                    closeAll();
                    break;
                }

                if ( len_message_from_origen < 0 )
                {
                    closeAll();
                    break;
                }

                message_origin = new byte[len_message_from_origen];

                //SAVE THE ORIGIN'S MESSAGE INTO AN ARRAY WHO HAS THE EXACT SIZE OF THIS MESSAGE
                System.arraycopy(buffer_msg_origin, 0, message_origin, 0, len_message_from_origen);

                aux = new String(message_origin);
                logger("RECEIVED MESSAGE FROM ORIGIN: " + aux);

                //MAKE THE CHANGES IN THE INPUT'S MESSAGE
                ChangesInMessages.makeChanges(message_origin,confs.type_changes_for_input_messages);
                aux = new String(message_origin);
                logger("RECEIVED MESSAGE FROM ORIGIN WITH MODIFICATIONS: " + aux);

                //I HAD TO PUT THIS BLOCK BECAUSE IF THE DESTINY APPLICATIONS FAILS
                //OR NOT ANSWER, THE PROGRAM MUST KEEP LISTENING THE FOLLOWING MESSAGES
                try
                {
                    //SENDING MESSAGE TO DESTINY
                    streamToDestiny.write(message_origin);

                    //READING THE ANSWER MESSAGE
                    logger("READING MESSAGE FROM DESTINY...");

                    //AT THIS POINY, WE MAY HAVE A PROBLEM IF THE SERVER DIES

                    len_message_from_destiny = streamFromDestiny.read(buffer_msg_destiny);
                }
                catch (SocketTimeoutException ex)
                {
                    logger("IT DIDN'T COULD RETRIEVE A MESSAGE FROM DESTINY (timeout): " + ex.getMessage());
                    continue;
                }
                catch (SocketException ex)
                {
                    boolean flagDestinyStillDead = false;

                    //IF WE REACH THIS EXCEPTION, IT MINDS THE DESTINY HAS DIED AFTER THE FIRST
                    //SUSSECCESFULLY CONNECTION, THUS, WE HAVE TO ASK IF THE DESTINY IS REALLY ALIVE
                    //HOW DO I DO THAT?

                    //I DONT KNOW HOW TO DO THIS SECCTION///

                    //NOTE: IF THE SERVER STILL DEAD, I HAVE TO CANCEL THIS MESSAGE AND
                    //RESTART THE LOOP
                    if ( flagDestinyStillDead )
                    {
                        closeAll();
                        break;
                    }
                }

                message_destiny = new byte[len_message_from_destiny];

                //SAVE THE DESTINY'S MESSAGE INTO AN ARRAY WHO HAS THE EXACT SIZE OF THIS MESSAGE
                System.arraycopy(buffer_msg_destiny, 0, message_destiny, 0, len_message_from_destiny);
                aux = new String(message_destiny);

                logger("RECEIVED MESSAGE FROM DESTINY " + aux);

                //MAKE THE CHANGES IN THE OUTPUT'S MESSAGE
                ChangesInMessages.makeChanges(message_destiny,confs.type_changes_for_output_messages);
                aux = new String(message_destiny);
                logger("RECEIVED MESSAGE FROM DESTINY WITH MODIFICATIONS: " + aux);

                //SENDING THE ANSWER BACK TO THE ORIGIN
                logger("SENDING BACK THE MESSAGE TO ORIGIN...");
                streamToOrigen.write(message_destiny);

                logger("MESSAGE DELIVERED SUCCESSFULLY!");
            } //INTERNAL LOOP OF MESSAGES

        } //INTERNAL LOOP OF CLIENTS
    } //TRY
    catch(IOException ex ) 
    {
        logger("THE SERVICE DIED: " +  ex.getMessage() );
        ex.printStackTrace();
    } //CATCH 
} //RUN

private void closeDestinyStream() throws IOException
{
    streamFromDestiny.close();
    streamToDestiny.close();
}

private void closeOriginStream() throws IOException
{
    streamFromOrigin.close();
    streamToOrigen.close();
}

private void closeAll() throws IOException
{
    closeDestinyStream();
    closeOriginStream();
}

private void logger(String message)
{
    System.out.println(Utilidades.date() + " " + prefix_log_messages + " " + message);
}
}

此致!

抱歉我的英语不好,我不是母语人士。

我将尝试使用我在评论中对 "alive" 和 "dead" 的定义来回答您的问题。所以我们知道,如果服务器在5秒内没有响应,那就死定了。另外,如果我们在5秒内无法连接到服务器,那么服务器也死了。

我们可以这样检查它是否是alive/dead:

boolean flagDestinyStillDead = false;

//give the server 5 seconds to do whatever it needs to get back alive
try {
    Thread.sleep( 5000 );
}
catch ( InterruptedException ie ) {
    //ignore this. this probably won't happen unless you purposely cause it
}

//we now create a new connection, because the old connection died
socketToDestiny = new Socket();

//we try connecting to the server
try {
    socketToDestiny.connect(new InetSocketAddress(confs.destiny_ip,confs.destiny_port), 5000 );

    //if our connection was successful, we also need to create a new input and output stream
   streamToDestiny = new DataOutputStream( socketToDestiny.getOutputStream() );
   streamFromDestiny = new DataInputStream( socketToDesinty.getInputStream() );

    //we give the server 5 seconds to respond to any of our messages
    socketToDestiny.setSoTimeout( 5000 );

   //ask the server if its alive
   streamToDestiny.writeUTF( "Are you alive?" );

   //if the server responds, then by our definition of "alive", the server is alive
   String receivedMessage = streamToDestiny.readUTF();
   if ( receivedMessage.equals( "Yes, I am alive now!" ) ) {
        flagDestinyStillDead = false;
   }

   //if the server did not respond, then we would get a SocketTimeoutException
   //and we never would reach here

}
catch ( SocketTimeoutException e ) {

    //server had 5 seconds to accept our connection, and since the connection timed out
    //we presume that the server is still dead
    flagDestinyStillDead = true;
}
catch ( IOException e ) {

    //we gave the server 5 seconds already to get back alive using Thread.sleep(...)
    //if any of our communications fail, then the server must be dead.
    flagDestinyStillDead = true;
}

所以,这是我们的英文流程:

 1. We lost connection to the server, oh no!

 2. Ok, well if it doesn't respond in around 5 seconds, then we'll
    presume it died

 3.   Fine, we'll wait 5 seconds.

 4.   Ok, 5 seconds passed. Let's connect again with 5 second timeout.

   4.1  Connection is reestablished. Ok, now we send the server a message to check that it can respond.

     4.1.1 We send the server a message and it responds. Ok, it's alive

     4.1.2 We send the server a message and it doesn't respond after 5 seconds. Ok, it's dead

   4.2  Connection is not reestablished. Ok, well we already waited 5 seconds. Since the server won't connect even after 5 seconds is up, we presume it's dead.

请注意,当我执行 streamToDestiny.writeUTF( "Are you alive?" ) 时,您需要服务器上的某种 readUTF() 代码才能阅读此邮件。然后服务器要writeUTF( "Yes, I am alive now!" );回来。您必须修改这一小部分代码以适应您的服务器和客户端的运行方式。