Closing connection issue

75 views
Skip to first unread message

marcel

unread,
Feb 19, 2009, 1:03:44 PM2/19/09
to jPOS Users
I wrote a client that connects to a Base24 server on the bank and
processes a few transactions then logs off and finishes.

The first execution of the client went OK with no problems at all, but
when I ran the client again the server was constantly reseting the
connection after the logon message.

The guy at the bank said that the problem was that my client was not
closing the tcp connection and that's why I couldn't connect again.

I tried closing the connection with mux.terminate() and
channel.discconect() but they all had the same effect. They both sent
a RST packet to terminate the TCP connection. The thing was that the
server on the other side didn't support that method(the guy said
something about the code being written for atms) so basically I wanted
to close the connection gracefully sending the FIN packet and waiting
for the other side to close the connection as well.

I found no way of doing this with JPOS(is there one?), instead I had
to override the closeSocket() method on BaseChannel to close the
socket gracefully changing this line:

socket.setSoLinger (true, 0); to
socket.setSoLinger (false, 0);

This change made it work perfectly.
Perhaps it would be nice that BaseChannel could be set to close
connections gracefully or not calling a method.

Just an idea!

Best regards,

Marcel

Mark Salter

unread,
Feb 19, 2009, 4:08:25 PM2/19/09
to jpos-...@googlegroups.com
marcel wrote:
> I found no way of doing this with JPOS(is there one?), instead I had
> to override the closeSocket() method on BaseChannel to close the
> socket gracefully changing this line:
>
> socket.setSoLinger (true, 0); to
> socket.setSoLinger (false, 0);
>
> This change made it work perfectly.
That is interesting, and makes me wonder if something else is at play
here...

Courtesy of jGuru :-

http://www.jguru.com/faq/view.jsp?EID=33897

This suggests that the option and values currently used in BaseChannel
are correct; I read this piece and have assumed it was correct.


> Perhaps it would be nice that BaseChannel could be set to close
> connections gracefully or not calling a method.

From the above page:-

"
Linger set to true and linger time==0

No more receives or sends can be issued on the socket. The socket
send and receive buffers are both discarded. This means that if the OS
has data internally for the socket this data is not sent and not
received by the other end. The close() method returns immediately and
clears the send buffer in background.
"

I wonder...
...could the server have been blocking on a receive (expecting more data
from you) at the point of closure?

I am grasping at straws and only a trace of the network exchanges may
tell us. Is the problem easily repeatable, could 'we' do a trace - of
both ends?

--
Mark

Alejandro Revilla

unread,
Feb 19, 2009, 10:35:11 PM2/19/09
to jpos-...@googlegroups.com
> > I found no way of doing this with JPOS(is there one?), instead I had
> > to override the closeSocket() method on BaseChannel to close the
> > socket gracefully changing this line:
> >
> > socket.setSoLinger (true, 0); to
> > socket.setSoLinger (false, 0);
> >
> > This change made it work perfectly.

> That is interesting, and makes me wonder if something else is at play
> here...
>
> Courtesy of jGuru :-
>
> http://www.jguru.com/faq/view.jsp?EID=33897
>

Nice pointer. I wonder if using a non-zero value for the linger time
could do too, i.e:

socket.setSoLinger (true, 5);

Marcel, can you give it a try?

Alwyn Schoeman

unread,
Feb 20, 2009, 2:28:39 AM2/20/09
to jpos-...@googlegroups.com
I've seen that some people send a null byte before closing.  Suspect that server side handling is very implementation specific (and broken) in many cases.

Wouldn't closing a socket, break a blocking read and return -1 bytes read?

Alwyn Schoeman



On Fri, Feb 20, 2009 at 5:35 AM, Alejandro Revilla <a...@jpos.org> wrote:

> > I found no way of doing this with JPOS(is there one?), instead I had
> > to override the closeSocket() method on BaseChannel to close th
> > socket gracefully changing this line:
> >
> > socket.setSoLinger (true, 0); to
> > socket.setSoLinger (false, 0);
> >
> > This change made it work perfectly.

> That is interesting, and makes me wonder if something else is at play
> here...
>
> Courtesy of jGuru :-
>
>   http://www.jguru.com/faq/view.jsp?EID=33897
>

Mark Salter

unread,
Feb 20, 2009, 3:27:43 AM2/20/09
to jpos-...@googlegroups.com
Alwyn Schoeman wrote:
> I've seen that some people send a null byte before closing. Suspect that
> server side handling is very implementation specific (and broken) in many
> cases.
>
> Wouldn't closing a socket, break a blocking read and return -1 bytes read?

That is a good question. I wonder what this server might do with that
result?

A network trace of both ends could make interesting 'reading'.

--
Mark

marcel

unread,
Feb 26, 2009, 7:08:49 AM2/26/09
to jPOS Users
For what I have tested and according to this source
http://java.sun.com/j2se/1.5.0/docs/guide/net/articles/connection_release.html
using the socket.setSoLinger(true,X) will trigger an abortive release
of the connection, in other words using RST packets.

I also tried putting something >0 on the second parameter but there's
no noticeable effect, it still closes the connection using Reset.

On the other hand using setSoLinger(false,X) will trigger the orderly
connection close as in my case was needed for it to work properly.

Thanks a lot guys!

Marcel

Alejandro Revilla

unread,
Feb 26, 2009, 7:26:14 AM2/26/09
to jpos-...@googlegroups.com
Thank you for the follow-up and pointers.

We definitely want to use false there, what value do you think would be
safe for the timeout? I'm keen to default to 15 seconds.

shaner

unread,
Mar 1, 2009, 8:45:28 PM3/1/09
to jPOS Users
I still don't see how the second parameter in setSoLinger makes any
difference if the first parameter is false. The SUN impl of
setSoLinger below doesn't use the "linger" parameter when "on" is
false.

public void setSoLinger(boolean on, int linger) throws
SocketException {
if (isClosed())
throw new SocketException("Socket is closed");
if (!on) {
getImpl().setOption(SocketOptions.SO_LINGER, new Boolean(on));
} else {
if (linger < 0) {
throw new IllegalArgumentException("invalid value for SO_LINGER");
}
if (linger > 65535)
linger = 65535;
getImpl().setOption(SocketOptions.SO_LINGER, new Integer
(linger));
Reply all
Reply to author
Forward
0 new messages