Reputation: 1122
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
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.)
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.)
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, ...);
}
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).
Upvotes: 3
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
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