VB .NET: Adding Simple Client Socket Project Program Example
Create a new class library project and you might want to use the project and solution names as shown in the following Figure.
Rename the class to ServerSocket by renaming the source file to reflect the application that we are going to developed.
|
Add a new project to the Solution. Select the Solution folder > Right click mouse > Select Add context menu > Select New Project sub menu.
Select a new class library project and name it as ClientSocketVB.
Rename the class to ClientSocket by renaming the source file.
Add/edit the following Import directives at the top of the file.
Imports System Imports System.Net Imports System.Net.Sockets |
Add the following code for the ServerSocket class that include the Main() subroutine.
' This is a simple TCP and UDP based server. Public Class ServerSocket ' Winsock ioctl code which will disable ICMP errors from being propagated to a UDP socket. ' This can occur if a UDP packet is sent to a valid destination but there is no socket ' registered to listen on the given port. ' http://msdn.microsoft.com/en-us/library/bb736550(VS.85).aspx Public Const SIO_UDP_CONNRESET = -1744830452
' This routine repeatedly copies a string message into a byte array until filled. ' <param name="dataBuffer">Byte buffer to fill with string message</param> ' <param name="message">String message to copy</param> Shared Sub FormatBuffer(ByVal dataBuffer As Byte(), ByVal message As String)
Dim byteMessage As Byte() = System.Text.Encoding.ASCII.GetBytes(message) Dim index As Integer = 0
' First convert the string to bytes and then copy into send buffer While (index < dataBuffer.GetUpperBound(0)) Dim j As Integer For j = 0 To byteMessage.GetUpperBound(0) - 1 dataBuffer(index) = byteMessage(j) index = index + 1
' Make sure we don't go past the send buffer length If (index >= dataBuffer.GetUpperBound(0)) Then GoTo AfterFor End If Next AfterFor: End While End Sub
' Prints simple usage information. Shared Sub usage() Console.WriteLine("Executable_file_namee [-l bind-address] [-m message] [-n count] [-p port]") Console.WriteLine(" [-t tcp|udp] [-x size]") Console.WriteLine(" -l bind-address Local address to bind to") Console.WriteLine(" -m message Text message to format into send buffer") Console.WriteLine(" -n count Number of times to send a message") Console.WriteLine(" -p port Local port to bind to") Console.WriteLine(" -t udp | tcp Indicates which protocol to use") Console.WriteLine(" -x size Size of send and receive buffer") Console.WriteLine(".....Else default values will be used...") Console.WriteLine() End Sub
' <param name="args">Command line arguments</param> Shared Sub Main() Dim textMessage As String = "Server: ServerResponse" Dim localPort As Integer = 5150 Dim sendCount As Integer = 10 Dim bufferSize As Integer = 4096 Dim localAddress As IPAddress = IPAddress.Any Dim sockType As SocketType = SocketType.Stream Dim sockProtocol As ProtocolType = ProtocolType.Tcp
usage() Console.WriteLine()
' Parse the command line Dim args As String() = Environment.GetCommandLineArgs() Dim i As Integer For i = 1 To args.GetUpperBound(0) Try Dim CurArg() As Char = args(i).ToCharArray(0, args(i).Length) If (CurArg(0) = "-") Or (CurArg(0) = "/") Then Select Case Char.ToLower(CurArg(1), System.Globalization.CultureInfo.CurrentCulture) Case "l" ' Local interface to bind to i = i + 1 localAddress = IPAddress.Parse(args(i)) Case "m" ' Text message to put into the send buffer i = i + 1 textMessage = args(i) Case "p" ' Port number for the destination i = i + 1 localPort = System.Convert.ToInt32(args(i)) Case "t" ' Specified TCP or UDP i = i + 1 If (args(i) = "tcp") Then sockType = SocketType.Stream sockProtocol = ProtocolType.Tcp ElseIf (args(i) = "udp") Then sockType = SocketType.Dgram sockProtocol = ProtocolType.Udp Else usage() Exit Sub End If Case "x" ' Size of the send and receive buffers i = i + 1 bufferSize = System.Convert.ToInt32(args(i)) Case Else usage() Exit Sub End Select End If Catch e As Exception usage() Exit Sub End Try Next
Dim serverSocket As Socket = Nothing
Try Dim localEndPoint As IPEndPoint = New IPEndPoint(localAddress, localPort) Dim senderAddress As IPEndPoint = New IPEndPoint(localAddress, 0) Dim castSenderAddress As EndPoint Dim clientSocket As Socket Dim receiveBuffer(bufferSize) As Byte Dim sendBuffer(bufferSize) As Byte Dim rc As Integer
FormatBuffer(sendBuffer, textMessage)
' Create the server socket serverSocket = New Socket( _ localAddress.AddressFamily, _ sockType, _ sockProtocol _ ) Console.WriteLine("Server: Socket() is OK...")
' Bind the socket to the local interface specified serverSocket.Bind(localEndPoint) Console.WriteLine("Server: Bind() is OK...")
Console.WriteLine("Server: {0} server socket bound to {1}", sockProtocol.ToString(), localEndPoint.ToString())
If (sockProtocol = ProtocolType.Tcp) Then ' If TCP socket, set the socket to listening serverSocket.Listen(1) Console.WriteLine("Server: Listen() is OK. I'm listening for connection...") Else Dim byteTrue(4) As Byte
' Set the SIO_UDP_CONNRESET ioctl to true for this UDP socket. If this UDP socket ' ever sends a UDP packet to a remote destination that exists but there is ' no socket to receive the packet, an ICMP port unreachable message is returned ' to the sender. By default, when this is received the next operation on the ' UDP socket that send the packet will receive a SocketException. The native ' (Winsock) error that is received is WSAECONNRESET (10054). Since we don't want ' to wrap each UDP socket operation in a try/except, we'll disable this error ' for the socket with this ioctl call. byteTrue(byteTrue.GetUpperBound(0) - 1) = 1 serverSocket.IOControl(SIO_UDP_CONNRESET, byteTrue, Nothing) Console.WriteLine("Server: IOControl() is OK...") End If
' Service clients in a loop While (True) If (sockProtocol = ProtocolType.Tcp) Then ' Wait for a client connection clientSocket = serverSocket.Accept() Console.WriteLine("Server: Accept() is OK...") Console.WriteLine("Server: Accepted connection from: {0}", clientSocket.RemoteEndPoint.ToString())
' Receive the request from the client in a loop until the client shuts ' the connection down via a Shutdown. Console.WriteLine("Server: Ready to receive using Receive()...") While (True) rc = clientSocket.Receive(receiveBuffer) Console.WriteLine("Server: Read {0} bytes", rc) If (rc = 0) Then Exit While End If End While
' Send the indicated number of response messages Console.WriteLine("Server: Ready to send using Send()...") For i = 0 To sendCount - 1 rc = clientSocket.Send(sendBuffer) Console.WriteLine("Server: Sent {0} bytes", rc) Next
' Shutdown the client connection clientSocket.Shutdown(SocketShutdown.Send) Console.WriteLine("Server: Shutdown() is OK...")
clientSocket.Close() Console.WriteLine("Server: Close() is OK")
Else castSenderAddress = CType(senderAddress, EndPoint)
' Receive the initial request from the client rc = serverSocket.ReceiveFrom(receiveBuffer, castSenderAddress) Console.WriteLine("Server: ReceiveFrom() is OK...")
senderAddress = CType(castSenderAddress, IPEndPoint) Console.WriteLine("Server: Received {0} bytes from {1}", rc, senderAddress.ToString())
' Send the response to the client the requested number of times Console.WriteLine("Server: Ready to send using SendTo()...") For i = 0 To sendCount - 1 Try rc = serverSocket.SendTo(sendBuffer, senderAddress) Catch ' If the sender's address is being spoofed we may get an error when sending ' the response. You can test this by using IPv6 and using the RawSocket ' sample to spoof a UDP packet with an invalid link local source address. GoTo ContinueSendLoop End Try
Console.WriteLine("Server: Sent {0} bytes to {1}", rc, senderAddress.ToString()) ContinueSendLoop: Next
' Send several zero byte datagrams to indicate to client that no more data ' will be sent from the server. Multiple packets are sent since UDP ' is not guaranteed and we want to try to make an effort the client ' gets at least one. Console.WriteLine("Server: Ready to send using SendTo(), sleeping for Sleep(250)...") For i = 0 To 2 serverSocket.SendTo(sendBuffer, 0, 0, SocketFlags.None, senderAddress)
' Space out sending the zero byte datagrams a bit. UDP is unreliable and ' the local stack can even drop them before even hitting the wire! System.Threading.Thread.Sleep(250) Next End If End While Catch err As SocketException Console.WriteLine("Server: Socket error occurred: {0}", err.Message) Finally ' Close the socket if necessary If (Not IsNothing(serverSocket)) Then serverSocket.Close() Console.WriteLine("Server: Close() is OK...") End If End Try End Sub End Class |
Let change the DLL to EXE type program so that we can run it in console mode. Select the project folder > Right click mouse > Select Properties context menu.
|
Change the Application type: to Console Application and the Startup object: to Sub Main.
Next, build the project and make sure there is no error.
Then, run the project. Any error will be thrown by the exception handlers.
The following is the sample output.