Не удается подключиться к другому компьютеру через TCP

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

Попытка подключения не удалась, потому что подключенная сторона не ответила должным образом через некоторое время, или установленное соединение не удалось, потому что подключенный хост не ответил

В настоящее время программа отправляет только некоторую информацию о файле, который будет скопирован, и ничего не шифруется, так как я не могу отправить даже эту информацию.

Вот код для сервера (используется Invoke, потому что он запускается в отдельном потоке):

    private void Server_Start()
    {


        try
        {
            // Set port on 13000
            int port = 13000;

            //Get the ip adress for the server
            String localIp;

            using (var client = new WebClient())
            {
                // Try connecting to Google public DNS and get the local endpoint as IP
                // If failed to connect set IP as local IP
                if (CheckForInternetConnection())
                {
                    try
                    {
                        using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0))
                        {
                            socket.Connect("8.8.8.8", 65530);
                            IPEndPoint endPoint = socket.LocalEndPoint as IPEndPoint;
                            localIp = endPoint.Address.ToString();
                        }
                    }
                    catch (Exception e)
                    {
                        localIp = "127.0.0.1";
                    }
                }
                else
                {
                    localIp = "127.0.0.1";
                }
            }


            IPAddress IP = IPAddress.Parse(localIp);

            // Create listener and start listening 
            server = new TcpListener(IP, port);
            server.Start();

            // Buffer for data
            Byte[] bytes = new byte[256];
            String data = string.Empty;
            this.Invoke((MethodInvoker)(() => Log.Items.Add("Server started on ip: " + IP.ToString())));
            while (true)
            {

                // Accepting requests
                TcpClient client = server.AcceptTcpClient();

                // Get the stream object
                NetworkStream stream = client.GetStream();

                // Read length of file name
                byte[] nameLength = new byte[4];
                stream.Read(nameLength, 0, 4);
                int nameSize = BitConverter.ToInt32(nameLength, 0);

                // Read the name of file
                byte[] name = new byte[nameSize];
                stream.Read(name, 0, nameSize);
                String fileName = Encoding.UTF8.GetString(name);

                // Read size of file
                byte[] fileSizeB = new byte[4];
                stream.Read(fileSizeB, 0, 4);
                int fileSize = BitConverter.ToInt32(fileSizeB, 0);

                // Read start signal
                byte[] startB = new byte[9+1];
                stream.Read(startB, 0, 9);
                String start = Encoding.UTF8.GetString(startB);

                this.Invoke((MethodInvoker)(() => Log.Items.Add("Size of name: " + nameSize.ToString())));
                this.Invoke((MethodInvoker)(() => Log.Items.Add("Name of file: " + fileName)));
                this.Invoke((MethodInvoker)(() => Log.Items.Add("File size: " + fileSize.ToString())));
                this.Invoke((MethodInvoker)(() => Log.Items.Add("Start signal: " + start)));

                // Response to client
                byte[] message = Encoding.UTF8.GetBytes("Testmessage");
                stream.Write(message, 0, message.Length);
            }
            server.Stop();
            Log.Items.Add("Server started on ip: " + IP.ToString());
        }
        catch (Exception e)
        {
            this.Invoke((MethodInvoker)(() => Log.Items.Add(e)));
        }

    }

А вот код для клиента:

    private void button1_Click(object sender, EventArgs e)
    {
        IPAddress iP = IPAddress.Parse(ConnectIp.Text);
        int port = 13000;
        int buffersize = 1024;

        TcpClient client = new TcpClient();
        NetworkStream netStream;

        // Try to connect to server
        try
        {
            client.Connect(new IPEndPoint(iP, port));
        }
        catch(Exception ex)
        {
            this.Invoke((MethodInvoker)(() => Log.Items.Add(ex.Message)));
            return;
        }

        netStream = client.GetStream();

        String path = "D:\\testingEnv\\test1\\testing\\Matematika\\2017\\Školsko\\2017-SS-skolsko-B-1234-zad.pdf";

        String Filename = Path.GetFileName(path);

        // We wish to send some data in advance:
        // File name, file size, number of packets, send start and send end

        byte[] data = File.ReadAllBytes(path);

        // First packet contains: name size, file name, file size and "sendStart" signal
        byte[] nameSize = BitConverter.GetBytes(Encoding.UTF8.GetByteCount(Filename)); // Int
        byte[] nameB = Encoding.UTF8.GetBytes(Filename);
        byte[] fileSize = BitConverter.GetBytes(data.Length);
        byte[] start = Encoding.UTF8.GetBytes("sendStart");

        // Last packet constains: "sendEnd" signal to stop reading netStream
        byte[] end = Encoding.UTF8.GetBytes("sendEnd");

        // Creating the first package: nameSize, fileName, fileSize and start signal
        byte[] FirstPackage = new byte[4 + nameB.Length + 4 + 9];
        nameSize.CopyTo(FirstPackage, 0);
        nameB.CopyTo(FirstPackage, 4);
        fileSize.CopyTo(FirstPackage, 4 + nameB.Length);
        start.CopyTo(FirstPackage, 4 + nameB.Length + 4);

        // Send the first pckage
        netStream.Write(FirstPackage, 0, FirstPackage.Length);

        byte[] buffer = new byte[30];

        // Read the response
        netStream.Read(buffer, 0, 11);

        netStream.Close();



        client.Close();
    }

Друг пытался пробросить порт 13000, но это тоже не сработало. Мы даже пытались с отключенным брандмауэром, но ничего. Я искал в Интернете, но не смог найти решения проблемы.

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

Кто-нибудь знает, в чем здесь проблема?

заранее спасибо


person zeroth    schedule 25.02.2019    source источник
comment
Убедились ли вы, что localIp не является 127.0.0.1 при создании TcpListener?   -  person C.Evenhuis    schedule 25.02.2019
comment
Я предполагаю, что вы проверили, что IP-адрес, который использует ваш сервер, не 127.0.0.1... Затем убедитесь, что порт действительно открыт. Попробуйте подключиться извне к этому хосту: порт с помощью telnet или Putty, когда сервер работает.   -  person montonero    schedule 25.02.2019
comment
IP-адрес сервера записывается в приложении, поэтому я уверен, что это не локальный хост. Порт открыт и телнет к нему не подключается. Он подключается к моему компьютеру, который находится в сети (другой IP-адрес), как я уже упоминал в комментарии ниже.   -  person zeroth    schedule 25.02.2019


Ответы (1)


Вы пытались подключиться к вашему серверу с помощью telnet? «telnet localhost 13000» или с другого компьютера с правильным IP-адресом и номером адреса? Попробуйте это во время отладки кода вашего сервера. Если телнет работает, значит в клиентском коде есть проблема..

person vpalmu    schedule 25.02.2019
comment
Я пробовал, но он не подключается к другому компьютеру. Он подключается к локальной сети (не локальному хосту, а тому, на котором работает мой ноутбук). Приложение работает, если я подключаюсь к своему компьютеру по другому IP-адресу, который подключен к тому же маршрутизатору, но проводом. В чем проблема с клиентским кодом? - person zeroth; 25.02.2019
comment
Хорошо, с этой информацией я думаю, что проблема не в самом коде. Вместо этого похоже на проблему, связанную с сетью. Он работает локально и в одной и той же локальной сети. Вы можете попробовать проверить, виден ли IP-адрес ваших друзей (тот, который код сервера использует после его запуска) с вашей машины. Вы можете устранить это с помощью команд ping и tracert в окне командной строки. - person vpalmu; 25.02.2019
comment
И ping, и tracert истекают при использовании его IP. Он обнаружил, что его роутер не отвечает по протоколу ICMP, а tracert подключается. Мы пробовали как частный, так и общедоступный IP-адрес, но когда я использовал общедоступный IP-адрес в программе для запуска прослушивателя, он выдает исключение, говорящее, что запрошенный адрес недействителен в его контексте. - person zeroth; 25.02.2019
comment
Обнаружил, что пинг-запросы доходят до его роутера, просто он на них не отвечает. - person zeroth; 26.02.2019
comment
Ok. Я думаю, что все еще может быть что-то с брандмауэром. Для работы команды ping протокол ICMP должен быть разрешен на брандмауэре. Вы также можете попробовать проверить это другим способом: ваша машина является сервером, а ваш друг пытается подключиться со своей машины... возможно, брандмауэр лучше разрешает исходящие соединения. - person vpalmu; 26.02.2019
comment
Я чувствую себя глупо.... Мы исправили проблему. Я делился локальным IP-адресом вместо общедоступного. Не знаю, почему я думал, что это сработает... Сегодня я узнал кое-что новое. Все работает как задумано, но теперь у меня есть другой вопрос. Как избежать необходимости открывать порты для возможности подключения. Идея моего приложения заключается в том, чтобы быть p2p. Я знаю, что в .net есть библиотека p2p, но я ее не понимаю. Как мне это сделать? WCF ответ или что-то еще? - person zeroth; 26.02.2019
comment
Ну, я думаю, вам все еще нужен tcp и открытые порты с решением p2p. Для меня об этом вы можете прочитать раздел Брандмауэры и порты в этой статье: docs.microsoft.com/en-us/previous-versions/dotnet/articles/. Что касается используемой технологии, я бы посоветовал сначала создать собственное решение для p2p - в учебных целях. Затем вы также можете изучить некоторые уже существующие фреймворки и выбрать тот, который лучше всего соответствует вашим потребностям. - person vpalmu; 27.02.2019
comment
Большое спасибо за вашу помощь. Я сделаю все возможное. - person zeroth; 27.02.2019