I'm trying to connect to a remote machine using the TcpClient class, but it keeps failing:
An unhandled exception of type 'System.Net.Sockets.SocketException' occurred in System.dll
Additional information: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
Testing the code when the client and server are local works, but when I try connecting to a remote machine, it no longer works.
Here is the server code:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WebSocketServer
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Starting a new WebSockets server.");
WebSocketServer server = new WebSocketServer();
Console.WriteLine("The WebSocket server has started.");
bool userRequestedShutdown = false;
while (!userRequestedShutdown)
{
Console.ReadLine();
DialogResult result = MessageBox.Show("Do you want to shut the server down?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if (result == DialogResult.Yes)
{
userRequestedShutdown = true;
}
}
server.Stop();
}
class WebSocketServer
{
TcpListener server;
Thread connectionListener;
ConcurrentDictionary<TcpClient, Thread> clients = new ConcurrentDictionary<TcpClient, Thread>();
public WebSocketServer()
{
server = new TcpListener(IPAddress.Parse("127.0.0.1"), (int)Properties.Settings.Default["Port"]);
try
{
server.Start();
}
catch (Exception exception)
{
Console.WriteLine("Error while trying to start the server: {0}", exception.ToString());
}
connectionListener = new Thread(() =>
{
while (true)
{
Console.WriteLine("Waiting for a new client.");
try
{
TcpClient client = server.AcceptTcpClient();
Thread clientListener = new Thread(() =>
{
try
{
NetworkStream stream = client.GetStream();
byte[] buffer = new byte[1024];
Console.WriteLine("Wating for the client to write.");
while (client.Connected)
{
try
{
int bytesRead = stream.Read(buffer, 0, buffer.Length);
Console.WriteLine("Read {0} bytes from the client.", bytesRead);
string data = Encoding.UTF8.GetString(buffer).Substring(0, bytesRead);
Console.WriteLine("Read the following string from the client: {0}", data);
}
catch (Exception exception)
{
Console.WriteLine("Error while trying to read from a TCP client: {0}", exception.ToString());
break;
}
}
Console.WriteLine("Client disconnected. Removing client.");
}
catch (Exception exception)
{
Console.WriteLine("Error while trying to connect to a TCP client: {0}", exception.ToString());
}
client.Close();
clients.TryRemove(client, out clientListener);
});
clientListener.Start();
clients.TryAdd(client, clientListener);
}
catch (Exception exception)
{
Console.WriteLine("Error while trying to accept a TCP client: {0}", exception.ToString());
}
Console.WriteLine("A client has connected.");
}
});
connectionListener.Start();
}
public void Stop()
{
server.Stop();
connectionListener.Abort();
}
}
}
}
Here is the client code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace WebSocketClient
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Opening up a TcpClient.");
TcpClient client = new TcpClient();
client.Connect("<Remote Hostname>", <RemotePortNumber>);
Console.WriteLine("TcpClient has connected.");
NetworkStream stream = client.GetStream();
bool closed = false;
new Thread(() =>
{
while (!closed)
{
Console.WriteLine("Writing data to the stream.");
byte[] bytes = Encoding.UTF8.GetBytes("Hello, world.");
stream.Write(bytes, 0, bytes.Length);
Thread.Sleep(1000);
}
}).Start();
Console.ReadLine();
closed = true;
}
}
}
So what is the problem here? I am hosting the server on an Azure Virtual Machine, I have opened up the TCP port I am trying to use as the <RemotePortNumber>
in Windows Firewall on my remote server by setting both inbound and outbound rules to allow all traffic in and out of the machine on that port, and I have created a TCP endpoint on my Azure portal that maps the external port of my Virtual Machine's hostname to the internal, private port, of my Virtual Machine, both set to map the same port number of <RemotePortNumber>
for consistency. To connect, I am using a <Remote Hostname>
value of <MyServiceName>.cloudapp.net
. I have also tried connecting the stream by using IPAddress.Parse(<Public IP of my Azure Server>)
but have had no luck...it just keeps timing out, as if I am not formatting the hostname correctly or something. What am I missing? If anyone can provide some clues as to how to debug the issue, that would also be very helpful.
Update: Running a WireShark trace, I see a lot of these messages (is this bad? I think the TCP Retransmission might be okay if we take into account that for Azure you have to route packets from the public domain's port to the private port of the VM, but not sure about whatever the RST, ACK's are):
Update: Running Microsoft Message Analyzer, I see these messages on the Local Link Layer:
Note: My VM has an Internal IP of 100.75.20.78 and a Public IP of 191.238.37.130. It has the public domain name of ovidius.cloudapp.net. I am trying to host the application on TCP port 6490. I blacked out my personal IP address for the sake of not giving it up.
I have mapped the TCP port in the Azure portal from domain to VM as follows: