Archive

Posts Tagged ‘socket’

TCP Proxy in C# using Task Parallel Library

April 27, 2011 9 comments

Every now and then I have the need to proxy TCP communications, handy for things like viewing network traffic or proxying Silverlight or Flash requests. C# makes this pretty easy, and the Task Parallel Library (add-on to .NET 3.5 & shipped with .NET 4) simplifies the code with a nice fluent interface.

Here’s a quick example that works for proxying a VNC connection. There is one task for reading from the client and sending data to the server and another task for reading server responses and sending them to the client.

static TcpListener listener = new TcpListener(IPAddress.Any, 4502);

const int BUFFER_SIZE = 4096;

static void Main(string[] args) {
    listener.Start();
    new Task(() => {
        // Accept clients.
        while (true) {
            var client = listener.AcceptTcpClient();
            new Task(() => {
                // Handle this client.
                var clientStream = client.GetStream();
                TcpClient server = new TcpClient("10.0.1.5", 5900);
                var serverStream = server.GetStream();
                new Task(() => {
                    byte[] message = new byte[BUFFER_SIZE];
                    int clientBytes;
                    while (true) {
                        try {
                            clientBytes = clientStream.Read(message, 0, BUFFER_SIZE);
                        }
                        catch {
                            // Socket error - exit loop.  Client will have to reconnect.
                            break;
                        }
                        if (clientBytes == 0) {
                            // Client disconnected.
                            break;
                        }
                        serverStream.Write(message, 0, clientBytes);
                    }
                    client.Close();
                }).Start();
                new Task(() => {
                    byte[] message = new byte[BUFFER_SIZE];
                    int serverBytes;
                    while (true) {
                        try {
                            serverBytes = serverStream.Read(message, 0, BUFFER_SIZE);
                            clientStream.Write(message, 0, serverBytes);
                        }
                        catch {
                            // Server socket error - exit loop.  Client will have to reconnect.
                            break;
                        }
                        if (serverBytes == 0) {
                            // server disconnected.
                            break;
                        }
                    }
                }).Start();
            }).Start();
        }
    }).Start();
    Debug.WriteLine("Server listening on port 4502.  Press enter to exit.");
    Debug.ReadLine();
    listener.Stop();
}

This is for illustrative purposes only. If you decide to use this in production, you’ll need to use TcpListener.BeginAcceptTcpClient() for async connections, you’ll need error handling and logging, and you’ll want some sort of pool to manage (and clean up) client socket connections. Have fun, and let me know if you have concerns or suggestions.

Advertisements
Categories: C#, Task, tcp, TPL Tags: , , ,

Powershell to find the next available port

March 30, 2009 Leave a comment

Every now and then I’m installing service application on a development machine, and I just want to find the next available port that I can use. Here is a handy Powershell script to do that, which can be easily run as part of a deployment script.

param([int]$port = $(throw("Port required.")))
$isInUse = $FALSE
while(!$isInUse)
{
	trap [System.Net.Sockets.SocketException]
	{
		write-host "Unable to open socket on port $port."
		$script:port = $script:port + 1
		$script:isInUse = $TRUE;
		continue;
	}

	$listener = New-Object System.Net.Sockets.TcpListener([System.Net.IPAddress]::Any, $port)
	$listener.Start()
	write-host "Socket opened successfully on port $port."
	$listener.Stop()
	$isInUse = $FALSE
	break
}
return $port

The easiest way to call this is to include it directly in another powershell script, but if you want to save this as a script that you can call from a different script as a cmdlet, you need to execute this command first, which allows execution of unsigned scripts from the local machine.

set-ExecutionPolicy RemoteSigned

After you’re done with your processing, you may want to set this back to the default restricted setting:

set-ExecutionPolicy Restricted