【发布时间】:2015-01-09 15:15:52
【问题描述】:
我正在尝试创建两个应用程序之间的消息监视器。这个想法是这个监视器在简单的客户端/服务器应用程序中间工作,并将消息记录到标准输出。该程序必须防止客户端/服务器出现故障(断开连接、超时等)。在代码中,我将客户端称为“起源”,将服务器称为“命运”。问题是如果服务器在第一次成功连接后就死了,我不知道我怎么问命运还活着? (请参阅代码中的捕获异常)。我执行下一步:
1.- 我启动客户端/服务器应用程序
2.- 我启动我的程序(使用线程)
3.- 我从客户端向我的程序发送一条消息,我的程序将此消息传递给服务器,服务器响应我的程序,我的程序成功将消息传递回客户端。
4.- 现在,我终止并重新启动客户端/服务器应用程序(无需重新启动我的程序)
5.- 我重复步骤“3”,但此时,当程序到达“len_message_from_destiny = streamFromDestiny.read(buffer_msg_destiny);”时它产生了我需要编写的代码来询问服务器是否真的活着(这在这一步中是真的)”。在这种情况下尝试读取会产生一个“SocketException”,并带有以下描述:“软件导致连接中止:recv失败的 java 邮件”。
如果我输入我需要再次连接套接字和新流的所有指令的 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);
}
}
问候!
对不起,我的英语不是母语。
【问题讨论】:
-
你能给出你对“活着”和“死去”的定义吗?例如,我可以将“活着”定义为“当且仅当我向它发送消息时,它才在 5 秒内响应服务器是活着的。如果服务器在 5 秒内没有响应,则它暂时或永久死亡。 "
-
你好@user2570465,我开始了一个新问题,因为我对我的代码进行了一些更改。是的,服务器在等待传入消息时处于活动状态。我管理服务器,我知道它正在等待新消息。如果我在步骤“4”重新启动我的应用程序,一切正常,但是,我不想这样做。