My main confusion is not knowing who the Server will be or if there even has
Tcp and Udp over WinSockets require a listener to receive connection requests. All framework implementations use WinSocks and
therefore require a "host". The design of the host may not actually "serve" anything, but instead just connect in a peer-to-peer
like framework where each computer is a potential host and client.
The design, as mentioned in a previous post, is up to you.
The easiest implementation would be, in my opinion, to designate a computer as a server that listens for all connections and
dispatches all bytes to all connected parties. I don't know your business requirements, but I'd imagine that this will fit better
than a peer-to-peer solution.
Also, would UDP be better in this
case?
Can your application account or handle lost packets of data? If not, then use TCP.
TcpClient and TcpListener are a good start for basic TCP/IP network applications. They use underlying Windows Sockets and a stream
(NetworkStream) to read/write data across the network.
UdpClient is the Udp version of the above two classes.
So how do I send and receive data (byte arrays) among them.
The Tcp* classes as mentioned above use a simple "NetworkStream : Stream" class that you can read/write to. It's intuitive if you
have worked with Streams of any form in the framework. So sending and receiving bytes becomes pretty easy.
A few things to consider:
1. You have to come up with your own implementation for how to receive logical groups of bytes:
A. All sends are prepended with a fixed-length byte header (1-byte command, 8-byte message length)
(I've used the above pattern and it works nicely. Of course the header could be whatever you need)
B. Logical groups of bytes are sent over "owened" connections. State-less protocols use this method. Of course, the connection
is no longer useable since the end-of-stream is determined by the connection termination.
C. End-of-message mark of some sort. For instance, at the end of all send operations, a byte-mark of a fixed-length and value
is appended. Of course, the data in the stream before the byte-mark cannot be of or contain the byte-mark. This is a questionable
approach since it is unlikely in most real-world apps that a byte-mark could be determined as always unique. It also may have a
negative effect on performance since you'd have to iterate all received bytes and match for the byte-mark.
2. You have to be able to handle network/socket errors. Unfortunately, there isn't a framework TCP implemenation that fires an
event when a socket connection is terminated, which leads into the next point...
3. You should implement some sort of graceful disconnection sequence. The first-byte in my header example could be used for this
command. (Say a Byte Enum where 1 = Greeting, 2 = Disconnect)
4. It's a pain to handle all of the "SocketException.ErrorCode"'s in a switch statement, although it should be done in order to
properly diagnos application bugs/issues. Many of the error codes can be handled in one statement, but some must be handled
differenty.
5. You must consider multi-threaded operations for performance and other reasons. This implies the coding of thread-safe methods
which adds another layer of complexity to the application.
I'm sure there's more.
Here's one more idea (that may be much less effort):
MSMQ may be a solution for you. The message queuing system ensures message delivery, even upon network failures (when the system is
back online). Larger systems using MSMQ require a designated monitoring station (i forget the exact terminology), but it may be
possible to do this peer-to-peer like for an intranet app. I'm sorry I can't provide more information about MSMQ, but research may
be worth the effort.
GL