I have an application that wants to open a Socket, write data and close the
socket. A persistent connection would be nice, but it's intended to
operate in an environment where the network connection probably isn't
reliable.

So I do this:

// open socket
m_networkSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
IPEndPoint them = new IPEndPoint(IPAddress.Parse(hostname), port);
m_networkSocket.Connect(them);
m_networkConnection = new NetworkStream(m_networkSocket, false);

// write
m_networkConnection.Write(arrayOfBytes, 0, arrayOfBytes.Length);
m_networkConnection.Flush();

// close
m_networkConnection.Flush();
m_networkConnection.Close();
m_networkSocket.Close();


All fine & good, but nothing shows up on the other side. If I put a delay
between Flush() and Close() it suddenly starts to work.

So is Flush() is a no-op?

Close() (for both Socket and NetworkStream) has an optional "timeout" value
(an Int32), which is 'the amount of time to wait for data to be sent'. I
_assume_ that's milliseconds, but does anyone know for sure?

That begs the question, however, of just how long do I wait? How do I know
my data has been sent and it's safe for me to close the connection?

Thanks!

al

--
Al Dunstan, Software Engineer
OptiMetrics, Inc.
3115 Professional Drive
Ann Arbor, MI 48104-5131

Re: Close() timeout in NetworkStream and Socket? by Peter

Peter
Wed Aug 27 17:36:18 CDT 2008

On Wed, 27 Aug 2008 12:16:19 -0700, A. W. Dunstan <no@spam.thanks> wrote:

> [...]
> All fine & good, but nothing shows up on the other side. If I put a
> delay
> between Flush() and Close() it suddenly starts to work.
>
> So is Flush() is a no-op?
>
> Close() (for both Socket and NetworkStream) has an optional "timeout"
> value
> (an Int32), which is 'the amount of time to wait for data to be sent'. I
> _assume_ that's milliseconds, but does anyone know for sure?

From the MSDN documentation: "Wait up to timeout seconds to send any
remaining data, then close the socket". But that's not really what you
want.

> That begs the question, however, of just how long do I wait? How do I
> know
> my data has been sent and it's safe for me to close the connection?

The correct way to manage the connection is to call
Socket.Shutdown(SocketShutdown.Send) when you're done sending data, and
then call Socket.Receive() until you get return value of 0.

I would not expect Stream.Flush() to do much of anything. The Socket
class is likely to be passing data off to the network driver as fast as it
can. Any delays in transmission are likely due to the Nagle algorithm,
which is responsible for coalescing data sent on a TCP connection, to
ensure efficient use of the connection.

Most likely what was happening in your example is that the socket was
being closed before the network driver got around to sending the data (it
was waiting a few hundred ms to see if you sent any more that it could
combine with what you'd already sent), aborting the transfer. There are
different ways to deal with this, but the best way is to manage the
connection in the expected way.

Pete

Re: Close() timeout in NetworkStream and Socket? by A

A
Thu Aug 28 09:05:12 CDT 2008

Peter Duniho wrote:

>> Close() (for both Socket and NetworkStream) has an optional "timeout"
>> value
>> (an Int32), which is 'the amount of time to wait for data to be sent'. I
>> _assume_ that's milliseconds, but does anyone know for sure?
>
> From the MSDN documentation: "Wait up to timeout seconds to send any
> remaining data, then close the socket". But that's not really what you
> want.
Ah - I'd been relying on the Visual Studio online help which made no mention
of units.

>> That begs the question, however, of just how long do I wait? How do I
>> know
>> my data has been sent and it's safe for me to close the connection?
>
> The correct way to manage the connection is to call
> Socket.Shutdown(SocketShutdown.Send) when you're done sending data, and
> then call Socket.Receive() until you get return value of 0.
>
> I would not expect Stream.Flush() to do much of anything. The Socket
> class is likely to be passing data off to the network driver as fast as it
> can. Any delays in transmission are likely due to the Nagle algorithm,
> which is responsible for coalescing data sent on a TCP connection, to
> ensure efficient use of the connection.
>
> Most likely what was happening in your example is that the socket was
> being closed before the network driver got around to sending the data (it
> was waiting a few hundred ms to see if you sent any more that it could
> combine with what you'd already sent), aborting the transfer. There are
> different ways to deal with this, but the best way is to manage the
> connection in the expected way.

Thanks! I'll give that a try shortly.

My transmission is purely one-way - send only. After calling Shutdown() do
I still need to call Receive()? Or is Shutdown() followed by Close()
sufficient to tell the socket "I'm done sending - finish up"?

--
Al Dunstan, Software Engineer
OptiMetrics, Inc.
3115 Professional Drive
Ann Arbor, MI 48104-5131

Re: Close() timeout in NetworkStream and Socket? by Peter

Peter
Thu Aug 28 10:35:20 CDT 2008

On Thu, 28 Aug 2008 07:05:10 -0700, A. W. Dunstan <no@spam.thanks> wrote:

> [...]
> My transmission is purely one-way - send only. After calling Shutdown()
> do
> I still need to call Receive()? Or is Shutdown() followed by Close()
> sufficient to tell the socket "I'm done sending - finish up"?

No, you need to call Receive(). As an alternative, you can set the
DontLinger socket option to false and specify a non-zero timeout (see
Socket.SetSocketOption()). But even in that case, if the timeout is
exceeded, transmission of the data will be aborted. To ensure that your
end has done everything it can to send the data, you need to call
Receive() and wait for the 0 byte return value.

That assumes, of course, that you want that behavior. For some
applications, a timeout in completing the send is appropriate, and you
would in fact be better off with the DontLinger approach. It just depends
on what you want your network i/o to do.

Pete