Я пытаюсь подключиться к удаленному компьютеру с использованием класса TcpClient, но он продолжает терпеть неудачу:
Необработанное исключение типа "System.Net.Sockets.SocketException" произошло в System.dll
Дополнительная информация: попытка подключения завершилась неудачно, потому что связанная сторона не ответила должным образом через какое-то время или не удалось установить соединение, потому что подключенный хост не смог ответить
Тестирование кода, когда клиент и сервер работают локально, но когда я пытаюсь подключиться к удаленному компьютеру, он больше не работает.
Вот код сервера:
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();
}
}
}
}
Вот код клиента:
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;
}
}
}
Так в чем проблема? Я размещаю сервер на Azure Virtual Machine, я открыл TCP-порт, который я пытаюсь использовать в качестве <RemotePortNumber>
в брандмауэре Windows на удаленном сервере, установив как входящие, так и исходящие правила, чтобы разрешить весь трафик в и из машина на этом порту, и я создал конечную точку TCP на моем портале Azure, которая сопоставляет внешний порт моего имени виртуальной машины с внутренним частным портом моей виртуальной машины, оба настроены на сопоставление того же номера порта <RemotePortNumber>
для согласованности. Чтобы подключиться, я использую значение <Remote Hostname>
<MyServiceName>.cloudapp.net
. Я также попытался подключиться к потоку с помощью IPAddress.Parse(<Public IP of my Azure Server>)
но IPAddress.Parse(<Public IP of my Azure Server>)
не повезло... он просто держит тайм-аут, как если бы я не форматировал имя хоста правильно или что-то в этом роде. Что мне не хватает? Если кто-то может дать некоторые подсказки относительно того, как отладить проблему, это также будет очень полезно.
Обновление: запустив трассировку WireShark, я вижу много таких сообщений (это плохо? Я думаю, что Retransmission TCP может быть в порядке, если учесть, что для Azure вам нужно маршрутизировать пакеты из порта общедоступного домена в частный порт VM, но не уверены в том, что RST, ACK):
Обновление. Запуск Microsoft Message Analyzer, я вижу эти сообщения на локальном уровне ссылки:
Примечание. Моя виртуальная машина имеет внутренний IP-адрес 100.75.20.78 и публичный IP-адрес 191.238.37.130. Он имеет общедоступное доменное имя ovidius.cloudapp.net. Я пытаюсь разместить приложение на TCP-порту 6490. Я поменял свой личный IP-адрес, чтобы не отказываться от него.
Я сопоставил порт TCP на портале Azure от домена к виртуальной машине следующим образом:
Проведя две мамы _______ дней на этом (заполните пробелы), я немного поработал, чтобы изучить альтернативные методы, чтобы попытаться выяснить, могу ли я решить проблемы маршрутизации. Я могу в значительной степени уверенно заключить, что маршрутизация виртуальной машины Microsoft терпит неудачу, когда вы сопоставляете публичный порт с тем же частным портом.
Например, я попытался настроить новую конечную точку Socket ниже, и она работала, потому что она не сопоставила тот же доменный порт с тем же портом виртуальной машины, как я ранее делал с WebSocketServer:
Обновление. Кроме того, при размещении я должен был настроить сервер, а не IP-адрес 127.0.0.1, но внутренний IP-адрес, который в моем случае равен 100.75.20.78.
Обновление снова: вопреки приведенному выше решению, я попытался удалить старую конечную точку на 6490 и воссоздал ее, и, похоже, она работает, когда я подключаюсь к этому адресу сейчас. Я не совсем понимаю, почему, я могу только сказать, что единственное отличие здесь в том, что у меня были правила брандмауэра, чтобы разрешить этот порт конечной точки до создания конечной точки на этот раз... не уверен, что это изменит ситуацию. Я честно не знаю, что вызвало проблемы.
Обновление еще раз: просто подумал об этом еще... Я думаю, что это сводится к следующим двум вопросам: