In Part 1 of this article I showed how one might use UDP datagrams to discover a client or server on a connected system over an IPv4 network. In Part 2 I am going to add a subsequent TCP connection and briefly explain how it is done.
Now we add a TCP connection.
There is more than one way to approach adding a TCP connection to this example. One of the simpler to understand approaches would be to use UDP to broadcast the listener’s IP back to the broadcaster after the listener received the broadcaster’s IP, and then create a TCP connection between the two specific IPs.
I am not using the above described method however. It seems to me to be a more usable approach to have the broadcaster asynchronously wait for an incoming TCP connection from any source, and once the connection is made authentication can be performed, but as with Part 1, I leave authentication and error handling up to the reader to implement.
Since we are using an asynchronous model for the TCP connection and communications, the pattern that all operations will follow is:
- Operation
- Callback
- Wait on Callback
We will also be using custom events to implement our waiting operations. These are created on lines 28 of the UDPBroacaster project and lines 27-29 of the UDPListener project.
Resolve the TCP address to an Endpoint
The first step we perform here is to resolve the TCP address that we are using to an endpoint object for the TCP client object to initialize itself with.
For the listener this is done using the IP received in the UDP datagram:
IPEndPoint remoteEP = new IPEndPoint(tcpAddress, tcpPort);
For the broadcaster this is done using it’s own host IP since we are accepting connections from any other address.
IPEndPoint localEndPoint = new IPEndPoint(localIP, tcpPort);
Connect to the Broadcaster
Once we have the endpoints we now attempt a connection to the UDPBroadcast application from the UDPListener application:
// Connect to the remote endpoint client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client); connectDone.WaitOne(); // Without these waits other processing could continue listView.Items.Add("TCP Connection Established with UDPBroadcaster");
Asynchronously wait for connection
Now we listen for an incoming connection request from anyone within the UDPBroadcast application:
// Bind the socket to the local endpoint and listen for incoming connections // This logic will parrot back any message received listener.Bind(localEndPoint); listener.Listen(100); // Start an asynchronous socket to listen for connections listener.BeginAccept( new AsyncCallback(AcceptCallback), listener); // Wait until a connection is made before continuing allDone.WaitOne(); listView.Items.Add("TCP Connection has been Established, and message received and returned");
The above listening logic for the UDPBroadcast application will asynchronously listen for a TCP connection, and once established, will wait for a message, read the message and return the same message back to the sender. You can see all the logic for the above within the AcceptCallback() method which you can view by downloading the example projects for this tutorial.
Send some test data
Now that we have a connection established, we can send some data to make sure everything is connected up correctly. We send a test message from within the UDPListener application:
// Send test data to the remote device Send(client, "Hello, this is UDPListener!<EOF>"); sendDone.WaitOne(); listView.Items.Add("Message sent to UDPBroadcast");
In a real application this initial message would likely be where you authenticate the connection between the two applications.
Wait for responce
Since the UDPBroadcast application is designed to parrot back any message it receives we can immediately wait for a response within the UDPListener application:
// Receive the response from the remote device Receive(client); receiveDone.WaitOne(); listView.Items.Add("Received the following responce from UDPBroadcast: "+response);
Close the Connection
Now that we have connected, sent, and received back data from the UDPBroadcast application we can close the TCP connection and release the socket:
// Release the socket client.Shutdown(SocketShutdown.Both); client.Close(); listView.Items.Add("Connection to UDPBroadcast application has been closed.");
Final Comments
The above is a very basic example, and as mentioned before error handling and proper authentication is necessary for using this in any real application. Much of the described logic is encapsulated within the callback methods that can be viewed by downloading the completed example projects linked at the bottom of this article.
I hope this has been helpful to those that have come here to read it. And as always if you have suggestions for improvements to this article, or comments about anything that I’ve done wrong, please leave a comment below.
References:
As always please refer to my references for further detail. Much of the code has been compiled from the linked references. For the UDP references see Part 1 of this series.
https://msdn.microsoft.com/en-us/library/bew39x2a(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/fx6588te(v=vs.110).aspx