WebSocket Session closes after not receiving input for some time - java

So I have a Websocket Session that reads information from a server. However if I cut off the information that it's receiving completely, after about a minute or so it will stop receiving new information, and won't do anything, even when the output from the server is turned back on.
I thought that the WebSocketContainer method
setDefaultMaxSessionIdleTimeout(Long time)
would fix my issue, so I set it to
container.setDefaultMaxSessionIdleTimeout(86400000L);
which I thought would mean it will continue running up to 1 day of inactivity.
However this is not the case, it stops after just a minute of inactivity. Below is the code I'm using, maybe someone can let me know what I'm doing wrong:
public void run(String... args) throws Exception {
log.info("Starting...");
log.info("-- API URL: {}", apiUrl);
log.info("-- API Token: {}", apiToken);
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
container.setDefaultMaxSessionIdleTimeout(86400000L);
ClientEndpointConfig config = ClientEndpointConfig
.Builder.create()
.configurator(new CustomConfigurator(apiToken))
.build();
try {
session = container.connectToServer(ConsumerClient.class, config, URI.create(apiUrl));
} catch (DeploymentException de) {
log.error("Failed to connect - DeploymentException:", de);
} catch (IOException ioe) {
log.error("IOException:", ioe);
}
if (this.session == null) {
throw new RuntimeException("Unable to connect to endpoint.");
}
log.info("Max Idle Timeout: " + session.getMaxIdleTimeout());
log.info("Connected.");
log.info("Type \"exit\" to cancel.");
log.info("...Waiting for data...");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String input;
try {
do {
input = br.readLine();
if (!input.equals("exit")) {
this.session.getBasicRemote().sendText(input);
}
} while (!input.equals("exit"));
} catch (IOException e) {
log.error("IOException:", e);
}
}
I'm fairly new to websockets so I may be completely misunderstanding something, but I hope someone will be able to point me in the right direction. Thanks in advance!

Can you try setMaxIdleTimeout(0) on the session?
According to the setDefaultMaxSessionIdleTimeout docs:
The value may be overridden on a per session basis using Session.setMaxIdleTimeout(long)

Related

Apache commons FPTSClient explicit transfer file is incomplete

Iam currently struggling a little bit with the FTPSClient from Apache Commons. See code down below. I try to write a file to FTP Server (vsftpd) when using FTPClient things are working perfectly fine. When using my code snippet I will always get a 451 Error, when debugging and waiting after Util.copyStream() returned everything works fine or settings a Thread.sleep(100). This also does not happen when I do not set the ftpsClient.execProt("P). Does anyone know by what this could be caused.
final FTPSClient client;
client = new FTPSClient("TLS", false);
client.setUseClientMode(true);
client.setDefaultPort(21);
// connect
try {
client.connect("serverAddress", 21);
} catch (SSLException e) {
throw e;
}
// setup any after connected
client.setSoTimeout(300);
client.setListHiddenFiles(true);
client.enterLocalPassiveMode();
FTPClientConfig ftpConfig;
try {
ftpConfig = new FTPClientConfig(client.getSystemType());
} catch (FTPConnectionClosedException e) {
throw e;
} catch (IOException e) {
ftpConfig = new FTPClientConfig();
}
client.configure(ftpConfig);
final FTPSClient ftpsClient = client;
// remove data buffer limit
ftpsClient.execPBSZ(0);
// set data channel encrypted
ftpsClient.execPROT("P");
client.login("user", "password");
if (!FTPReply.isPositiveCompletion(client.getReplyCode())) {
throw new IOException("Authentication failed: " + client.getReplyString().trim());
}
// postconfigure connection
if (!client.setFileTransferMode(FTP.STREAM_TRANSFER_MODE) || !client.setFileType(FTP.BINARY_FILE_TYPE)) {
throw new IOException("Failed to correctly configure client: " + client.getReplyString().trim());
}
InputStream input;
OutputStream output;
input = new FileInputStream(pathToLocalFile);
output = client.storeFileStream("foobar.txt");
final var number = Util.copyStream(input, output);
System.out.println(number);
input.close();
// Thread.sleep(100);
output.close();
// Must call completePendingCommand() to finish command.
if (!client.completePendingCommand()) {
client.logout();
client.disconnect();
System.err.println("File transfer failed.");
}
This library has been around for a long time, and things change a bit under the hood. Try:
input = new FileInputStream(pathToLocalFile);
boolean result = client.storeFile("foobar.txt", input);
if (result) {
System.out.println("\tFile Transfer Completed Successfully");
}
I have noticed that every once in a while when transferring files to a mainframe, it won't complete. I think it has something to do with the file length, but I've never been able to track it down. I also don't use the stream_transfer_mode.

Java socket write error when client disconnects from server

I am working on a chat app in Java and so far everything works all right except that when a client disconnects and a message is send by other client this error pops out:
java.net.SocketException: Software caused connection abort: socket write error
at java.base/java.net.SocketOutputStream.socketWrite0(Native Method)
at java.base/java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:110)
at java.base/java.net.SocketOutputStream.write(SocketOutputStream.java:150)
at java.base/java.io.DataOutputStream.write(DataOutputStream.java:107)
at java.base/java.io.DataOutputStream.writeUTF(DataOutputStream.java:401)
at java.base/java.io.DataOutputStream.writeUTF(DataOutputStream.java:323)
at com.terkea/com.terkea.system.server.ClientThread.run(ClientThread.java:65)
at java.base/java.lang.Thread.run(Thread.java:835)
This is my server Thread:
#Override
public void run() {
try {
DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
while (!socket.isClosed()) {
try {
String input = in.readUTF();
if (Message.fromJSON(input).getUserName().equals("REGISTER")) {
Message specialMessage = Message.fromJSON(input);
specialMessage.setUserName("SERVER");
Client test = Client.fromJSON(specialMessage.getMessage());
test.setIp(socket.getInetAddress().toString());
test.setListening_port(String.valueOf(socket.getPort()));
specialMessage.setMessage(Client.toJSON(test));
input = Message.toJSON(specialMessage);
}
for (ClientThread thatClient : server.getClients()) {
DataOutputStream outputParticularClient = new DataOutputStream(thatClient.getSocket().getOutputStream());
outputParticularClient.writeUTF(input);
}
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
and the Client:
public void createClient() {
try {
socket = new Socket(getHost(), portNumber);
DataInputStream in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
Message registerclient = new Message("REGISTER", Client.toJSON(getClient()));
out.writeUTF(Message.toJSON(registerclient));
new Thread(() -> {
while (!socket.isClosed()) {
try {
if (in.available() > 0) {
String input = in.readUTF();
Message inputMessage = Message.fromJSON(input);
if (inputMessage.getUserName().equals("SERVER")) {
System.err.println(Client.fromJSON(inputMessage.getMessage()));
allClientsConnected.add(Client.fromJSON(inputMessage.getMessage()));
} else {
chat.add(inputMessage);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
}
The error corresponds to outputParticularClient.writeUTF(input);
My goal is to get rid of this error and also if possible could anybody tell me a way to check when a client disconnects? I've found some similar questions over here and their solution was to check if (socket.getInputStream().read()!=-1)
but when I do that the whole program freezes and the GUI stops working.
You may want to look into expanding upon your special message functionality, and instead of using the username to pass "REGISTER" use something like messageType in order to do so. This way you can configure handlers based on type to do a number of things. For example things like:
MessageType { REGISTER, UNREGISTER, READ_RECEIPT, ... }
You can then have things like:
RegisterHandler {}
UnregisterHandler{}
and eventually expand them to have some features like facebook/whatsapp (/ICQ haha):
TypingHandler {} // Other user gets a message saying that I am typing to them
From here, you can implement the UNREGISTER to do what you want. Like the first comment says, you should catch the SocketException and manually unregister that client so it doesn't happen anymore. But you should also try to pre-emptively send an
{
messageType: UNREGISTER,
from: Client1
to: server|null,
data: {}
}
so that your server can remove it before the exception occurs. This would also let you handle Offline messages, if that's something you're interested in.

java socket disconnected from server side

I am facing a problem regarding sockets on the server side. My code is client side. Whenever I am sending a second message (whether it's a heartbeat or any other message) it will fail on the server, and the server side logs an 'error in message format' but the same message will succeed the first time.
Please help me out with this.
my client code :
public class Main {
String Host = "";
int port = 1111;
Socket ss;
BufferedReader in;
BufferedWriter out;
String recv;
public void connection() {
try {
ss = new Socket(Host, port);
ss.setSoTimeout(30000);
in = new BufferedReader(new InputStreamReader(ss.getInputStream()));
out = new BufferedWriter(new OutputStreamWriter(ss.getOutputStream()));
} catch (UnknownHostException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void sender(String regTag) {
if (ss == null || !ss.isConnected()) {
connection();
}
try {
if (out != null && regTag != null) {
out.write(regTag + "\n");
System.out.println("message::" + regTag);
out.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public String Reciver() {
try {
recv = in.readLine();
if (ss != null && recv != null) {
return recv;
} else {
disconnect();
String Str = "nothing...Sorry";
return Str;
}
} catch (Exception e) {
e.printStackTrace();
return "Exception";
}
}
public void disconnect() {
try {
System.out.println("socket discoonected.");
ss.close();
in.close();
out.close();
connection();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Main me = new Main();
me.connection();
String hbhb = "`SC`0004HBHBB7BDB7BD";
String login = "`SC`00581.000000CRBTSRVM 00000001DLGLGN 00000002 TXBEG LOGIN:USER=cvbs,PSWD=password DEB2CCA8";
String cut = "`SC`00631.000000CRBT00PPSPHS00000002DLGCON 00000003 TXBEG CUT PPS FEE:MDN=9610023,CUTFEE=1000,REASON=1 BDB7DA88";
me.sender(hbhb.trim());
String str = me.Reciver();
System.out.println("Response :::" + str);
me.sender(login.trim());
String str1 = me.Reciver();
System.out.println("Response hb:::" + str1);
}
It receives null ... all the time on every second message
logs from serverside
[121_SERVER] 2012-05-03 14:26:37:213 [ERROR] [ServerAccptor.java:254] ->
errorCode = [UIP-80015] errorDesc = [Uip server has a exception when receiving data from the client,will remove the client,Server [adapter id=121],.]
at com.ztesoft.zsmart.bss.uip.adapter.socket.server.ServerAccptor.listenMsg(ServerAccptor.java:252)
at com.ztesoft.zsmart.bss.uip.adapter.socket.server.ServerAccptor.run(ServerAccptor.java:117)
Caused by: errorCode = [UIP-9102] errorDesc = [] Describing= [read client message error,will remove client.]
at com.ztesoft.zsmart.bss.uip.adapters.socket.server.mml.MMLServerAdapter.readByteField(MMLServerAdapter.java:784)
at com.ztesoft.zsmart.bss.uip.adapters.socket.server.mml.MMLServerAdapter.reciveWholeMsg(MMLServerAdapter.java:671)
Your code embodies numerous bad practices and fallacies.
You are logging exceptions and otherwise ignoring them, and doing strange things like letting the program continue, returning "Exception", etc. This is poor programming. Exceptions are there to help you, not to have bandaids applied them to hide the blood. The code will not self-heal under the bandaid. For example you should just declare connection() to throw IOException and let the callers deal with it.
As a consequence of (1) you have numerous ss != null tests. You shouldn't even be in a state where you need to do I/O and ss could be null. Again correct exception handling and propagation would avoid this.
As a further result of (1), you have numerous !ss.isConnected() tests, apparently in the mistaken belief that this API will tell you if the connection has been dropped. It won't. It will only tell you whether you have connected the Socket yet. In your code, as you are calling ss = new Socket(...), you have connected it, or else you haven't executed that code yet. Calling isConnected() adds no value.
You are closing the socket input stream before the output stream. This is incorrect. You should close only the output stream, and the socket itself in a finally block. That way the output stream gets flushed. Closing the input stream closes the socket and the output stream without flushing it. Don't do that.
Actually the correct answer is that there is no \n in the MML response. So this never works:
recv = in.readLine();
You have to read the message length given in the message header part of the response and read up to that length.
UPDATE:
there are syntax errors in your MML commands. It seems that you are using version 1.00 of the protocol, so this is a sample that works (look for differences):
`SC`00741.00CRBT PPS 00000001DLGCON 00000004TXBEG PPS CUT FEE:mdn=93784050910,fee=300,id=20140812165011003 F3E0ADDF
You must fill the extra spaces with 0 just in numbers, elsewhere you have to fill them with blank spaces.

.read() throws intermittent SocketTimeoutException even though data should be there

I'm working on a web server for Android and even though I've spent days trying to fix it, I'm at my wits' end with this particular bug. I'm trying to read the request from the browser, and the code works fine most of the time, but something like 5% of the requests fail and it throws random SocketTimeoutExceptions without even reading a single character from the Socket.
I have tested this with different browsers and it happens with all of them, so chances are the problem is on my end. Here's the relevant code, stripped down as far as possible:
public class ServerThread extends Thread {
private ServerSocket ss = null;
private boolean isRunning;
private ExecutorService threadPool = new ThreadPoolExecutor(2, 12,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy());
public ServerThread() {
}
public synchronized void run() {
ss = new ServerSocket(8080, 1);
isRunning = true;
while (isRunning) {
Socket clientSocket = null;
try {
if (ss != null) {
clientSocket = ss.accept();
if (isRunning) {
this.threadPool.execute(new HTTPSession(clientSocket));
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
And:
public class HTTPSession implements Runnable {
private Socket mSocket = null;
public HTTPSession (Socket s) {
mSocket = s;
}
public void run() {
InputStream ips = null;
try {
mSocket.setSoTimeout(15000);
ips = mSocket.getInputStream();
ips.read();
}
catch (Exception e) {
e.printStackTrace();
Log.v("HTTPSession", "Socket connected: " + mSocket.isConnected() + ", Socket closed: " + mSocket.isClosed() + ", InputShutdown: " + mSocket.isInputShutdown());
}
finally {
try { ips.close(); } catch (IOException ioe) { }
try { mSocket.close(); } catch (IOException ioe) { }
}
}
}
So ServerThread accepts the connection, HTTPSession tries to read from the Socket and sometimes it throws the SocketTimeoutException after the 15 seconds are up.
The output from the Log statement in the catch in this case is:
Socket connected: true, Socket closed: false, InputShutDown: false
What gives? Surely 15 seconds is enough of a wait and it seems unlikely that mainstream web browsers just aren't sending any data, so why can't I read it?
I would appreciate any input on this problem.
SocketTimeoutException only means one thing: no data was available within the timeout period. So yes maybe your timeout is too short, and yes the browser didn't send it within the timeout period, or at least it didn't arrive at the server's socket receive buffer within the timeout period.
I would say 15 seconds is a bit aggressive for a server side timeout. 30s to a couple of minutes would be more like it.
I don't see any reason this code would fail in that way unless, like you said, a browser just wasn't sending anything. You could change the ips.read(); to System.out.println(ips.read()); to be sure of that. If you see a byte show up on stdout, then the browser did send something. My guess would be that in your full code, you're not properly recognizing the end of a request and continuing to wait for more data. After 15 seconds, you'll time out. But that's just a guess. If you post some code that demonstrates the problem, someone might be able to give you a definitive answer.

Java/android socket.close() is not realized by server

I'm having an issue trying to get a java server to realize an (android/java) client has closed a TCP socket connection. I figured when the client calls close() on the socket, the server would catch an IOException, but this is not the case. t_recv is a thread that receives from BufferedReader in, and t_send sends using a PrintWriter out. Closing in causes a timeout and crash, and closing out doesn't really seem to do anything. The PrintWriter is created in the contructor of the t_send thread, and BufferedReader is create in the contructor of the t_recv thread. Trying to debug this, I created blank run() methods in both threads, and the same behaviour occurs.
An interesting note: the client is an Android application, and whenever the emulator freezes and windows has to force close it, the IOException is caught in the server and the "User x.x.x.x left" message is displayed.
Client closing connection:
try {
// t_recv.in.close(); - times out and crashes
// t_send.out.close(); - appears to do nothing
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
Server waiting for client to disconnect:
for (;;)
{
try {
while ( (msg = in.readLine()) != null)
{
response = msg;
System.out.println(response);
server.broadcast(response);
}
} catch (IOException e) {
System.out.println("User '" + socket.getInetAddress().toString() + "' left");
try {
socket.close();
out.close();
in.close();
} catch (IOException e1) {
e1.printStackTrace();
System.exit(-1);
}
break;
}
}
Thanks for your time.
Assuming that in is a BufferedReader, the error is in this line:
while ( (msg = in.readLine()) == null);
That will loop for ever if in is currently at the EOF. It should be:
while ( (msg = in.readLine()) != null);
See javadoc for BufferedReader.readLine(), paying specific attention to the conditions in which it returns null.

Categories