[jcifs] Disconnect from a share

Michael B Allen mba2000 at ioplex.com
Fri Aug 12 20:21:22 GMT 2005


On Fri, 12 Aug 2005 14:23:41 +0200
Mathias Dietz <MDIETZ at de.ibm.com> wrote:

> After some debugging (comparing tcp packages from smbclient with jcifs), I
> found two causes for the "Broken Pipe" error.
> 
> 1) doDisconnect() sends a LogoffAndX packet and doesn't wait for the
> response.
>    This causes a server error message (Error writing xx bytes to client).
>    Solution: In SMBSession.logoff(boolean) replace
>        transport.send( request, null );
>       with
>        transport.send( request, new SmbComLogoffAndX(null));

Ok, I think I see what's happening. But first, note that second
parameter to SmbTransport.send() is actually a response object so
passing an SmbComLogoffAndX is invalid. You got lucky because the
SmbComLogoffAndXResponse decodes no data. A more appropriate object
would be SmbComBlankResponse.

But passing null to the transport indicates that it should not to wait
for the response. This is slightly faster since we can move on to other
things rather than sit there collecting a logging off response which
has no useful information in it.

The problem is that first of "other things" is to close the socket but
apparently Samba hasn't written it's response yet so when it tries to
do so it get's an error (albeit a harmless one).

> 2) The Java VM sends a TCP RST package when you close the socket, smbclient
> sends a TCP FIN package.
>    I found a description of the problem here:
>    http://java.sun.com/security/javaone/2003/2240-Networking.pdf
>    Solution: In SMBTransport.doDisconnect(..) add:
>             socket.shutdownOutput();
>    above of ->
>             out.close();
>             in.close();

Interesting! I never noticed this. I would prefer to send a FIN. I'll
add this to The List.

If you do 2 and not 1 does it fix the error? I would rather NOT wait
for the logoff response.

> I'm still very interessted in a disconnect() method , because I use jcifs
> to monitor multiple samba servers (up to 100).
> And I must create a new connection each 10-15 seconds.A disconnect() method
> would help to save a lot of
> resources (# of threads) und would make life easier.

Again, the proper solution here is to add refcounting to the
transport. That way you can leave soTimeout at 15 seconds (actually in
your case you would probably want to make it 5 seconds) but when a request
is outstanding on the transport it cannot be closed. That change is too
invasive for me to add to mainline while we're in a stable period so
you might elect to simply extend SmbFile to add your disconnect() method.

Note that depending on what your doing a change in algorithm might
dramatically improve performance. Double check that the problem really
is that your not getting a response from the server for 2+ minutes. It
could be something else. For example, the naive way to write a crawler
is to do post order DFS. The problem with that is that you end up with
a huge list of nodes that have an expired attExperiationPeriod and/or
the transport has timed out. That means that when that node is examined
again jcifs needs to query the attributes again and/or create the
transport. That is horribly slow. The solution is to keep the crawing
list very short. Meaning do listFiles() and then query those nodes
immediately. Meaning used breadth first search. When combined with a
thread pool performance can be quite good.

Mike


More information about the jcifs mailing list