Advertisement:

Skystone Software

http://www.SkystoneSoftware.com

.NET Programming

Network Communications in .NET
Published: 5/18/2007

Since the second computer was built, people have wanted to be able to get these machines to talk to each other. Doing so requires that one of them is listening for communication requests that the other might be sending (I'm told that women expect men to work this way too, but have no first-hand experience, myself). This computer doing the listening is commonly referred to as a "server", because it's purpose is to listen for requests, and serve up responses to them. The computers that send these communication requests are referred to as "clients" - they are consumers of the server's product. In a typical chat program, all of the network clients act as both servers and clients using some combination of the different code blocks that are provided in this article (the trick is to use more than one port, dynamically choosing which port computer A will send on and which port computer B will send on - the details of that are outside the scope of this article).

Sending the messages over TCP/IP requires the use of Sockets, which have been nicely wrapped in .NET by the System.Net.Sockets class, and is as simple as calling the Connect and Send methods using the proper parameters. The following code will send a text message ("Hello World!") to the computer using the local IP address "192.168.2.106":

        
Try
    Dim clsError As System.Net.Sockets.SocketError
    Dim bMessage As Byte() = System.Text.Encoding.ASCII.GetBytes("Hello World!")
    Dim clsSocket As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
    clsSocket.Connect("192.168.2.106", 1972)
    clsSocket.Send(bMessage, 0, bMessage.Length, SocketFlags.None, clsError)
    If clsError = SocketError.Success Then
		MessageBox.Show(Me, "Message sent!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Information)
	Else
        MessageBox.Show(Me, "The message was not sent successfully, the message was: " & clsError.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
    End If
Catch ex As Exception
    MessageBox.Show(Me, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try			
			

Receiving these messages requires the use of the same objects, but in different ways:

' create listener socket...
Dim clsEndpoint As IPEndPoint = New IPEndPoint(New IPAddress(New Byte() {192, 168, 2, 106}), 1972)
Dim clsServerSocket As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
' bind to the IP address and port - this blocks other listeners from using the same combination...
clsServerSocket.Bind(clsEndpoint)
' listen for incoming connections...
clsServerSocket.Listen(CInt(Fix(SocketOptionName.MaxConnections)))
Do
    ' poll for connections - this allows us to keep listening so the thread doesn't block...
    If clsServerSocket.Poll(10000, SelectMode.SelectRead) Then
        ' a message is being sent - create a socket to read it...
        Dim clsSocket As Socket = clsServerSocket.Accept()
        ' read the message from the buffer...
        Dim bReadBuffer As Byte() = New Byte(255) {}
        clsSocket.Receive(bReadBuffer, bReadBuffer.Length, SocketFlags.None)
        ' convert to a string...
        Dim sMessage As String = ""
        sMessage = System.Text.Encoding.ASCII.GetString(bReadBuffer)
        'display message...
        MessageBox.Show(Me, sMessage, "Incoming Message", MessageBoxButtons.OK, MessageBoxIcon.Information)
        ' release socket...
        clsSocket.Close()
        clsSocket = Nothing
    End If
Loop	
	

The above code will loop continually, always listening for incoming connections and displaying them in a MessageBox when they are received (of course, this action blocks the listening action and isn't practical in real life - it's just for the purposes of illustration).

Another limitation of the code above is that the message received can be no longer than 255 bytes. In order to send data longer (or shorter) than that, you would have to work some sort of data length indicator into your message and use the overload of the Receive method that accepts the Offset and Length parameters. For example, include the length of the text data in the first N characters of the message. If the text you wanted to send was:

"Hello World!"

...then you would instead send:

"0000000012Hello World!"

The first 10 digits in this case indicate how many more characters follow in the message. You could then create a buffer with a length of 10, call the Receive method that accepts an Offset and Length parameter (passing 0, and 10, respectively), read the value received and resize the buffer accordingly, and then call the Receive method again passing in the new Offset (10 and N - 10, respectively).

NOTE: The System.Net.Sockets namespace also provides TcpListener and TcpClient classes which provide similar functionailty, but I prefer to use the Sockets class directly as it enables you more control over the details of your send / receive communications.



Written by Scott Waletzko for Skystone Software.
Copyright 2005-2007 by Echosoft Design Studios, LLC, All Rights Reserved.