If client Socket
is defined like this:
args = new SocketAsyncEventArgs();
args.AcceptSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
await args.AcceptSocket.ConnectAsync(host, port);
and server lets it get connected in this way:
server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(new IPEndPoint(0, port));
server.Listen(0);
var arg = new SocketAsyncEventArgs();
arg.AcceptSocket = await server.AcceptAsync();
Are the byte[]
used in Send/SendAsync
and Receive/ReceiveAsync
for transmission between server and client exact equivalent to NetworkStream
, which we get by calling tcpClient.GetStream()
for reading/writing, of TcpListener
and TcpClient
?
I'm not sure BUT I think they are because SocketType
for both client and server is set to Stream
and there shouldn't be any data loss in send/receive
between those Streaming
protocols!
The difference is one of API design.
The .NET
Socket
class is an OOP API for Win32's Winsock, which itself is derived from BSD Sockets.The
Socket
API is built around its own functions for sending and receiving data, with functions likesend
,recv
. On many platforms you can use the OS-provided filesystem API for reading and writing to sockets the same way you can read and write to local files.In .NET, the
Stream
class exists as an abstraction of any source or sink for binary data which can be read in a blocking or non-blocking (async
) manner regardless of where it came from (a file on a local disk, a file on a network share, a buffer in-memory, a TCP connection, a UDP connection, and so on). Read more aboutStream
and its use as an abstraction here: https://learn.microsoft.com/en-us/dotnet/standard/io/The point is that if you write a program or library that processes data - then rather than having to repeat your code over-and-over for different types of IO (files, in-memory buffers, TCP connections, etc) you only need to write your code once using
Stream
and then magically your code can be used in many new places without much work.But this comes with a downside of leaky-abstractions. We've since learned over the past 20-30 years of software-engineering that a single interface will not be perfect in every role - for example, a
MemoryStream
is always non-blocking and doesn't need flushing - but aNetworkStream
(aStream
API forSocket
) behaves very differently despite sharing the same API (remember: interfaces do not describe behavior!), such as how it buffers data internally (e.g. Nagle's algorithm). This is why .NET is now moving away fromStream
and towards the newPipeline
API model.So, in short:
Socket
internally.TcpClient
object adapts theSocket
API to theStream
API (asNetworkStream
).TcpClient
cannot exist without aSocket
.NetworkStream
is simply an adapter forSocket
for theStream
API.Stream
API then you should only use theSocket
API and not useNetworkStream
orTcpClient
.Stream
model, then useTcpClient
andNetworkStream
- but be-aware of howNetworkStream
behaves and you should always use non-blocking (async, aka "overlapped IO") to avoid bottlenecks and program freezes.