Get the client's IP address using TcpClient in VB.NET






4.24/5 (28 votes)
How to get the client's IP address using TcpClient in VB.NET.
Introduction
This article demonstrates how to get the IP address for a remote client using the TcpClient
object. There is already a nice solution for this in managed C++ here, but I needed to do this in VB.NET. Unfortunately, I could not get the cast that was used in the C++ solution to work in VB.NET. In addition, there is a much easier way that works in any .NET language!
Background
At TrayGames, we use the TcpListener
object to establish a client-server communication for our multi-player online game platform. When a client connects to our server, we use the AcceptTcpClient
method to accept the pending request which returns a TcpClient
object to us. You could use the AcceptSocket
method which gives you greater flexibility, returning a Socket
object, but we wanted to use the TcpClient
object.
Using the Code
The ClientConnection
class encapsulates the TcpClient
object. The full implementation of this class handles the sending and receiving of data across the TCP connection, but that's not the point of this article, so that code has been left out. The point of this article is the code that belongs in the PublicIPAddress
property, which I'll show in minute. Only the basic members and methods are shown in the class below, though I've left the IDisposable
implementation for completeness:
Imports System.Net.Sockets
Imports System.Reflection
Public NotInheritable Class ClientConnection
Implements IDisposable
Private Client As TcpClient
Private PublicIP As String
' TODO: Add code for PublicIPAddress property here
Public Sub New(ByVal client As TcpClient)
' Validate parameters
If client Is Nothing Then
Throw New ArgumentNullException("client")
End If
Me.Client = client
End Sub
#Region " IDisposable Support "
Private disposedValue As Boolean ' To detect redundant calls
Private Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
' TODO: free unmanaged resources here
If Not Client Is Nothing Then
Client.Close()
Client = Nothing
End If
End If
' TODO: free shared unmanaged resources
End If
Me.disposedValue = True
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code
' in Dispose(ByVal disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
One of the following properties, which demonstrate two different ways to get the remote IP address, is meant to be added to the ClientConnection
class. The easiest way to get the IP address is to get the underlying Socket
object through the Client
method of the TcpClient
object. Once you have the underlying socket, you can make a call to the RemoteEndPoint
property which gets the EndPoint
that contains the remote IP address and port number to which the Socket
is connected. You must cast this EndPoint
to an IPEndPoint
before retrieving any information. You can then call the IPEndPoint.Address
method to retrieve the remote IP address as shown below:
Public ReadOnly Property PublicIPAddress() As String
Get
If PublicIP = String.Empty Then
Try
' Get the clients IP address using Client property
Dim ipend As Net.IPEndPoint = Client.Client.RemoteEndPoint
If Not ipend Is Nothing Then
PublicIP = ipend.Address.ToString
End If
Catch ex As System.ObjectDisposedException
PublicIP = String.Empty
Catch ex As SocketException
PublicIP = String.Empty
End Try
End If
Return PublicIP
End Get
End Property
The other way to get the underlying Socket
object is from a NetworkStream
object. This object can be retrieved through the TcpClient
object's GetStream
method. Unfortunately, the Socket
member is not accessible to us directly because it's marked Protected
. You could derive your own class from NetworkStream
, which is the solution used in the managed C++ article mentioned earlier, but the required cast doesn't seem to work in VB.NET. Instead, we can circumvent this protection by using a little reflection as shown below:
Public ReadOnly Property PublicIPAddress() As String
Get
If PublicIP = String.Empty Then
Try
' Get the clients IP address using reflection
Dim pi As PropertyInfo = _
client.GetStream.GetType.GetProperty( _
"Socket", BindingFlags.NonPublic Or BindingFlags.Instance)
If Not pi Is Nothing Then
PublicIP = pi.GetValue(client.GetStream, _
Nothing).RemoteEndPoint.ToString.Split(":")(0)
End If
Catch ex As System.Exception
PublicIP = String.Empty
End Try
End If
Return PublicIP
End Get
End Property
Either version of the PublicIPAddress
property will work fine. Note that you don't have to have a class that encapsulates the TcpClient
object, you only need the TcpClient
object itself for either of these techniques. That's all there is to it!
Points of Interest
This article is interesting if you want to learn some creative ways to manipulate the TcpClient
object which provides client connections for TCP network services. Although this wasn't the most complicated topic, hopefully, I've saved someone a little time figuring this out! If you are interested in creating your own multi-player online games, you should check out the TGSDK which is downloadable from the TrayGames web site.