TcpClient не подключается к удаленному серверу

1

Я пытаюсь подключиться к удаленному компьютеру с использованием класса 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):

Изображение 174551

Обновление. Запуск Microsoft Message Analyzer, я вижу эти сообщения на локальном уровне ссылки:

Изображение 174551

Примечание. Моя виртуальная машина имеет внутренний IP-адрес 100.75.20.78 и публичный IP-адрес 191.238.37.130. Он имеет общедоступное доменное имя ovidius.cloudapp.net. Я пытаюсь разместить приложение на TCP-порту 6490. Я поменял свой личный IP-адрес, чтобы не отказываться от него.

Я сопоставил порт TCP на портале Azure от домена к виртуальной машине следующим образом:

Изображение 174551

  • 1
    Подсказка, попробуйте телнет к вашему серверу. Если это удастся, проблема, скорее всего, будет у клиента. Если нет, проблема на сервере.
  • 0
    @alex Вы также можете попробовать traceroute, чтобы увидеть, как далеко вы добираетесь до сервера. Можете ли вы tcpdump на сервере, чтобы убедиться, что ответы генерируются обратно к клиенту?
Показать ещё 20 комментариев
Теги:
azure
sockets
tcp

1 ответ

3
Лучший ответ

Проведя две мамы _______ дней на этом (заполните пробелы), я немного поработал, чтобы изучить альтернативные методы, чтобы попытаться выяснить, могу ли я решить проблемы маршрутизации. Я могу в значительной степени уверенно заключить, что маршрутизация виртуальной машины Microsoft терпит неудачу, когда вы сопоставляете публичный порт с тем же частным портом.

Например, я попытался настроить новую конечную точку Socket ниже, и она работала, потому что она не сопоставила тот же доменный порт с тем же портом виртуальной машины, как я ранее делал с WebSocketServer:

Изображение 174551

Обновление. Кроме того, при размещении я должен был настроить сервер, а не IP-адрес 127.0.0.1, но внутренний IP-адрес, который в моем случае равен 100.75.20.78.

Обновление снова: вопреки приведенному выше решению, я попытался удалить старую конечную точку на 6490 и воссоздал ее, и, похоже, она работает, когда я подключаюсь к этому адресу сейчас. Я не совсем понимаю, почему, я могу только сказать, что единственное отличие здесь в том, что у меня были правила брандмауэра, чтобы разрешить этот порт конечной точки до создания конечной точки на этот раз... не уверен, что это изменит ситуацию. Я честно не знаю, что вызвало проблемы.

Обновление еще раз: просто подумал об этом еще... Я думаю, что это сводится к следующим двум вопросам:

  1. Вам необходимо разместить сервер на внутреннем IP-адресе вашей Azure Virtual Machine, а не localhost или 127.0.0.1, как я делал.
  2. Вам не нужно включать функцию ENABLE DIRECT SERVER RETURN на вашей конечной точке Azure.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню