B4J Question How to trap java.net.SocketException: Connection reset [solved]

Didier9

Well-Known Member
Licensed User
Longtime User
Here is how I am opening a TCP socket:
B4X:
    tcpSocket.Connect( IPAddress, EthernetPort, 5000 )
    Wait For tcpSocket_Connected( Connected As Boolean )
    If tcpSocket.Connected = True Then
        Astream.Initialize( tcpSocket.InputStream, tcpSocket.OutputStream, "AStream" )
        Log( "TCP socket is open" )
    Else
        Log( "TCP socket failed to open" )
    End If

That works fine, unless the socket is already open by another client. In that case, the server does open the socket but closes it immediately after the SYN-ACK/ACK ("Connection is forcefully rejected"). I do get this in the log:
B4X:
TCP socket is open
java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(SocketInputStream.java:210)
    at java.net.SocketInputStream.read(SocketInputStream.java:141)
    at java.net.SocketInputStream.read(SocketInputStream.java:127)
    at anywheresoftware.b4a.randomaccessfile.AsyncStreams$AIN.run(AsyncStreams.java:216)
    at java.lang.Thread.run(Thread.java:748)
java.net.SocketException: Connection reset by peer: socket write error
    at java.net.SocketOutputStream.socketWrite0(Native Method)
    at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)
    at java.net.SocketOutputStream.write(SocketOutputStream.java:143)
    at anywheresoftware.b4a.randomaccessfile.AsyncStreams$AOUT.run(AsyncStreams.java:355)
    at java.lang.Thread.run(Thread.java:748)
Error: (SocketException) java.net.SocketException: Connection reset by peer: socket write error
Error: (SocketException) java.net.SocketException: Connection reset by peer: socket write error
TimeOut: 0
I tried to separately declare a Sub tcpSocket( Connected as Boolean ) event to catch the socket being closed right after it is opened but
the event does not fire and my application is left to believe the socket is open.
How can I trap the SocketException event?

Here is a simple example that shows the problem (there will be no point running it if you do not have the proper target running the proper code to talk to it).
 

Attachments

  • dev 202110161758.zip
    6.9 KB · Views: 257
Last edited:

Didier9

Well-Known Member
Licensed User
Longtime User
Updated project, now saves settings to a map file and actually uses the port number entered in the form.
 

Attachments

  • dev 202110160955.zip
    6.8 KB · Views: 168
Last edited:
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
in addition to your command/interactive element, i see
you're using b4xpages. while the first isn't necessarily
a big problem, i have to say i don't know how b4xpages
is implemented and what connection it might have to
what's going on. the same is true, to a certain degree,
with asynch streams. somebody is waiting somewhere
for a reply. it was invented simply to permit the main
thread to proceed without an answer and not have
android kill the process. but somebody, in fact, is
waiting for the answer. how that thread is implemented
could be involved. what happens if the connection is
lost while a wait thread is waiting? who gets told?

i'm having a hard time envisioning what your app does, especially
since you have a command line version, which - to me - means
there isn't a gui or a timeout involved. in other words, why
asynch and pages? both, perhaps, may just be incidental, but
i think debugging becomes harder when you don't know what
various actors are doing.

i have seen the "Object should first be initialized (Exception)"
message before. as have others. my understanding is that
it means there was no exception but one was referenced in
code (obviously). hard to say from here why.

as to try/catch, you can wrap more than 1 statement in such a
block. but asynch disturbs that idea, since the event indicating
an answer can't be in the same block. and beyond not know
exactly how asynch is implemented, i'd be curious to see exactly
how you're handling the interaction between writing and eventually
getting an answer.

and depending on what your app actually does, my immediate
reaction is to change from asynch to regular streams, at least
until you see if you can try/catch writing and blocking for a reply
on a stream without a crash. or at least not catching one.
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
do you want to go pm with this, since no one else has any thoughts yet? i don't want rouse the forum police with too much discussion on a given topic. the feeling is if something isn't resolved in a couple of exchanges, it's time for a new theme. we can always bring it back to the forum if there is some resolution. the underlying issues are relevant to all, the actual solutions (if any) may not be. there was a time when people played postal chess, and a single game went on for years.
 
Upvote 0

Didier9

Well-Known Member
Licensed User
Longtime User
do you want to go pm with this, since no one else has any thoughts yet? i don't want rouse the forum police with too much discussion on a given topic. the feeling is if something isn't resolved in a couple of exchanges, it's time for a new theme. we can always bring it back to the forum if there is some resolution. the underlying issues are relevant to all, the actual solutions (if any) may not be. there was a time when people played postal chess, and a single game went on for years.
That is fine, apparently it's just you and me anyways.
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
see you on the other side. i wish somebody else had experienced somthing similar. and to keep the chess analogy going, erel is like the master playing 128 games simultaneously; he can't be expected to hover at length over every board. if you determine that an event isn't raised when it should be, he might have more to add.
 
Upvote 0

Didier9

Well-Known Member
Licensed User
Longtime User
I think I got it.
Erel suggested that I check if I had the AStream_Terminated() event.
I did but the app still crashed.
It turns out that after I added Try/Catch brackets around the AStream.Initialize statement in the ConnectedToServer function (after the socket is seemingly opened), the Terminate event was then called when the socket closed.
So AStream_Initialize does not fail, but the connection terminates some time later.

Then there was a secondary issue:
I had this in the AStream_Terminated event:
B4X:
Log( "AStream_Terminated: " & LastException.Message )
The problem was that the "LastException" message was causing a crash too.
I replaced that line with:
B4X:
Log( "AStream_Terminated" )
and now the event is properly handled.

Interestingly, the socket is still being opened, the Terminated event occurs a bit after trying to open AStream, and sometimes that occurs a second or two (!) after the socket is opened (note that this is early Sunday morning, the machine and the network are lightly loaded). I have no idea why the long delay but it no longer crashes the app and it properly reports the socket as closed, so I am happy.

Finally, I unplugged the server while being connected to see what happened.
After a minute or so, I got the AStream_Error event:
B4X:
java.net.SocketTimeoutException: Read timed out
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
	at java.net.SocketInputStream.read(SocketInputStream.java:171)
	at java.net.SocketInputStream.read(SocketInputStream.java:141)
	at java.net.SocketInputStream.read(SocketInputStream.java:127)
	at anywheresoftware.b4a.randomaccessfile.AsyncStreams$AIN.run(AsyncStreams.java:216)
	at java.lang.Thread.run(Thread.java:748)
 
Upvote 0

Didier9

Well-Known Member
Licensed User
Longtime User
Final piece of data:
I went back and removed the Try/Catch around AStream.Initialize() and it still works (i.e. the Terminate event catches the socket failing because it was closed by the server), so it seems like it was almost working, the only clear issues are that using LastException in the AStream_Terminated event absolutely caused a crash, and the socket closing is not reported as a socket_Connected() event, but as an AStream_Terminated event.
Also, AStream.Initialize on a closed socket does not cause an immediate error, so Try/Catch around Initialize if the socket is reported Open will not help.

I will go back to the old code to make sure these were the only issues.
 
Last edited:
Upvote 0
Top