Brian Tacker
Brian Tacker

Reputation: 1122

NetworkStream.Write vs. Socket.Send

I have a c# application that I use a custom FTP library for. Right now Im using Socket.Send to send the data but I was wondering if it would be better to initiate a NetworkStream with the socket and use NetworkStream.Write instead.

Are there any advantages to using one over the other?

Upvotes: 21

Views: 15987

Answers (3)

wilson0x4d
wilson0x4d

Reputation: 8749

One disadvantage of using the .NET Framework implementation of NetworkStream::Write is that if the underlying network (OSI layers 1-4) is unable to receive the entire data buffer you are not made aware (except, perhaps, by inspecting .NET Networking performance counters.)

Unreliable.

Something like this appears in NetworkStream::Write of Microsoft's .NET Framework System.dll:

try
{
    socket.Send(buffer, offset, size, SocketFlags.None);
}
/* ... catch{throw;} */

Note how the return value, which represents the count of bytes written by Send(), is discarded. This suggests NetworkStream::Write is unreliable for sub-par networks (roaming/wireless), or networks that may become IO bound (exceeding available bandwidth.)

More than one implementation.

You can find other implementations which write all bytes until all of buffer has been written (or other failure occurs.) It is a standard method of sending data, and will always exhibit the following behavior:

var count = 0;
while (count < size)
{
    count += socket.Send(buffer, offset + count, size - count, ...);
}

What does this mean?

You can write proper and reliable send() code by calling Socket::Send directly, you cannot write proper and reliable send() code calling NetworkStream::Write.

As an aside, other variations of NetworkStream do not have the same problem the BCL disassembly shows (see mono,cosi2), and still others show similar problems despite their best efforts (see flourinefx).

References

  1. Mono Repository on Github
  2. FlourineFxSL Source Code
  3. cosi2 Repository on BitBucket (via searchcode.com)

Upvotes: 3

Rick Sladkey
Rick Sladkey

Reputation: 34240

The advantage of a NetworkStream derives primarily from the fact that it is a Stream. The disadvantage of a Socket is that common code that reads and writes from abstract I/O sources like a Stream cannot handle a Socket.

The main use case for a NetworkStream is that you have some code elsewhere that reads or writes from a Stream, and you wish you could use it with a Socket. You would know if were in this situation and then NetworkStream would be a big help!

Say for example you had a communications library and you supported serializing messages from files, named pipes and TCP/IP. The ideal choice for the I/O class would be Stream. Then your serialization methods could accept a FileStream, a PipeStream, or a NetworkStream. It would even accept a MemoryStream. This is the benefit of abstraction because after we've created the stream, a method can interact with it without knowing what kind of stream it is.

In this sense, a NetworkStream uses the adapter design pattern. It adapts the Socket API to the Stream API so that clients that are expecting a Stream can use it.

So finally, the question, if NetworkStream is a Stream adapter for a Socket, which one should we use? Well, if you need a Stream, then NetworkStream is your only choice. If you don't need a Stream, then you can use whichever API you are most comfortable with. If you are already using Socket successfully, there is no pressing reason to switch to NetworkStream.

Upvotes: 29

DanNsk
DanNsk

Reputation: 900

You can potentially separate creation of NetworkStream and to work with that as with abstract Stream - so you'll be able to change your transport or simply to create Stream stubs for testing.

As a question of method itself - NetworkStream.Write inside has the only operation (except state checks) streamSocket.Send(buffer, offset, size, SocketFlags.None); - so it's mostly the same as to call that on socket.

Upvotes: 3

Related Questions