Немогу подключиться к TCP/IP серверу

199
31 марта 2022, 01:20

Запустил сервер но почему-то не могу к нему подключиться

Вот сервер :

// SocketServer.cs
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace SocketServer
{
    class Program
    {
        static void Main(string[] args)
        {
            // Устанавливаем для сокета локальную конечную точку
            IPHostEntry ipHost = Dns.GetHostEntry("localhost");
            IPAddress ipAddr = ipHost.AddressList[0];
            IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, 11000);
            // Создаем сокет Tcp/Ip
            Socket sListener = new Socket(ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            // Назначаем сокет локальной конечной точке и слушаем входящие сокеты
            try
            {
                sListener.Bind(ipEndPoint);
                sListener.Listen(10);
                // Начинаем слушать соединения
                while (true)
                {
                    Console.WriteLine("Ожидаем соединение через порт {0}", ipEndPoint);
                    // Программа приостанавливается, ожидая входящее соединение
                    Socket handler = sListener.Accept();
                    string data = null;
                    // Мы дождались клиента, пытающегося с нами соединиться
                    byte[] bytes = new byte[1024];
                    int bytesRec = handler.Receive(bytes);
                    data += Encoding.UTF8.GetString(bytes, 0, bytesRec);
                    // Показываем данные на консоли
                    Console.Write("Полученный текст: " + data + "\n\n");
                    // Отправляем ответ клиенту\
                    string reply = "Спасибо за запрос в " + data.Length.ToString()
                            + " символов";
                    byte[] msg = Encoding.UTF8.GetBytes(reply);
                    handler.Send(msg);
                    if (data.IndexOf("<TheEnd>") > -1)
                    {
                        Console.WriteLine("Сервер завершил соединение с клиентом.");
                        break;
                    }
                    handler.Shutdown(SocketShutdown.Both);
                    handler.Close();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            finally
            {
                Console.ReadLine();
            }
        }
    }
}

Вот клиент :

 #include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
/* hton, ntoh и проч. */
#include <arpa/inet.h>
#include <memory.h>
#include <stdio.h>
int main(int argc, char * argv[])
{
      /*объявляем сокет*/
      int s = socket( AF_INET, SOCK_STREAM, 0 );
      if(s < 0)
      {
              perror( "Error calling socket" );
              return 0;
      }
      /*соединяемся по определённому порту с хостом*/
      struct sockaddr_in peer;
      peer.sin_family = AF_INET;
      peer.sin_port = htons( 11000 );
      peer.sin_addr.s_addr = inet_addr( "127.0.0.1" );
      int result = connect( s, ( struct sockaddr * )&peer, sizeof( peer ) );
      if( result )
      {
              perror( "Error calling connect" );
              return 0;
      }
      /*посылаем данные
       *
       * Если быть точным, данные не посланы, а записаны где-то в стеке, когда и как они будут
       * отправлены реализации стека TCP/IP виднее. Зато мы сразу получаем управление, не
       * дожидаясь у моря погоды.*/
      char buf[] = "Hello, world!";
      result = send( s, "Hello, world!", 13, 0);
      if( result <= 0 )
      {
              perror( "Error calling send" );
              return 0;
      }
      /* закрываем соединения для посылки данных */
      if( shutdown(s, 1) < 0)
      {
              perror("Error calling shutdown");
              return 0;
      }
      /* читаем ответ сервера */
      fd_set readmask;
      fd_set allreads;
      FD_ZERO( &allreads );
      FD_SET( 0, &allreads );
      FD_SET( s, &allreads );
      for(;;)
      {
              readmask = allreads;
              if( select(s + 1, &readmask, NULL, NULL, NULL ) <= 0 )
              {
                      perror("Error calling select");
                      return 0;
              }
              if( FD_ISSET( s, &readmask ) )
              {
                      char buffer[20];
                      memset(buffer, 0, 20*sizeof(char));
                      int result = recv( s, buffer, sizeof(buffer) - 1, 0 );
                      if( result < 0 )
                      {
                              perror("Error calling recv");
                              return 0;
                      }
                      if( result == 0 )
                      {
                              perror("Server disconnected");
                              return 0;
                      }
                      if(strncmp(buffer, "Hi, dear!", 9) == 0)
                              printf("Got answer. Success.\n");
                      else
                              perror("Wrong answer!");
              }
              if( FD_ISSET( 0, &readmask ) )
              {
                      printf( "No server response" );
                      return 0;
              }
      }
      return 0;
}

А вот что он мне даёт на выходе:

сервер и клиент подключены к одному и тому же "разветвителю".

Почему то не подключается, увы так и не понял почему.

SocketServer.cs

    // Устанавливаем для сокета локальную конечную точку 
    IPHostEntry ipHost = Dns.GetHostEntry("localhost"); //несработало "172.16.8.169"
    // IPAddress ipAddr = ipHost.AddressList[0];
    IPAddress ipAddr = (Dns.Resolve(IPAddress.Any.ToString())).AddressList[0];
    IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, 11000);

client.c добавил:

  peer.sin_port = htons( 11000 );
  peer.sin_addr.s_addr = inet_addr( "172.16.8.169" );
  int result = connect( s, ( struct sockaddr * )&peer, sizeof( peer ) );

Почемуто не сработало

вот вызов ifconfig : На сервере

На клиенте

пинг пингуеться :

comp@comp0:~/Qt_project/TCP_CP$ ping 172.16.8.169:11000
ping: 172.16.8.169:11000: Неизвестное имя или служба
comp@comp0:~/Qt_project/TCP_CP$ ping 172.16.8.169
PING 172.16.8.169 (172.16.8.169) 56(84) bytes of data.
64 bytes from 172.16.8.169: icmp_seq=1 ttl=64 time=1.39 ms
64 bytes from 172.16.8.169: icmp_seq=2 ttl=64 time=1.31 ms
64 bytes from 172.16.8.169: icmp_seq=3 ttl=64 time=1.23 ms
64 bytes from 172.16.8.169: icmp_seq=4 ttl=64 time=1.36 ms
64 bytes from 172.16.8.169: icmp_seq=5 ttl=64 time=1.32 ms
64 bytes from 172.16.8.169: icmp_seq=6 ttl=64 time=1.30 ms
^C
--- 172.16.8.169 ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 5006ms
rtt min/avg/max/mdev = 1.237/1.322/1.394/0.056 ms

Вроде бы по ответу @Геннадия П всё верно и логически всё представлено верно но, почему то как то "не звучит цветомузыка".

Answer 1

Так как вы используете клиент и сервер на разных машинах, то ваша проблема в том, что вы слушаете так называемый loopback (localhost, 127.0.0.1) адрес, который используется только в пределах локальной машины.

Во-первых вам нужно слушать все интерфейсы:

IPAddress ipAddr = (Dns.Resolve(IPAddress.Any.ToString())).AddressList[0];

Во-вторых вам в клиенте нужно указывать IP-адрес сервера, например:

peer.sin_addr.s_addr = inet_addr( "192.168.1.100" );

Также не забудьте проверить файрвол на машине с сервером, т.к. он может блокировать входящие подключения.

Answer 2

В добавление к ответу @Геннадий-П:

  1. Создавайте сокет для сети IPv4. У меня, например, C# по-умолчанию создал сокет IPv6.
  2. Привяжите этот сокет ко всем адресам на машине - используйте в Bind адрес 0.0.0.0
  3. Разрешите в файерволе порт 11000.
  4. Используйте для тестирования утилиту netcat

Пункты 1 и 2.

Код создания и привязки сокета:

            // Устанавливаем для сокета локальную конечную точку - слушаем все сетевые интерфейсы
            IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 11000);
            // Создаем сокет Tcp/Ip
            Socket sListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

Dns.GetHostEntry вам совершенно не нужен в сервере. Этот функционал нужен клиентам, чтобы узнать адрес сервера.

Пункт 3 зависит от ОС. В Ubuntu: sudo ufw allow 11000

Пункт 4: на вашей тестовой машине (comp0 - верно?) выполните команду:

echo Hello! | nc <server_address> 11000

Здесь <server_address> - адрес сервера, на котором выполняется ваш EXE (R2CPU, судя по скриншоту)

Если всё настроено верно, то nc напечатает ответ сервера Спасибо за запрос в 7 символов

Я потестировал у себя. Сервер Windows 10, адрес 192.168.100.100, nc запускал на Ubuntu, адрес 192.168.100.101.

Сервер напечатал:

PS C:\tmp\tmp-stackexchange-csharp> .\SocketServer.exe
Ожидаем соединение через порт 0.0.0.0:11000
Полученный текст: Hello!

Ожидаем соединение через порт 0.0.0.0:11000

Пункт 4': команда для проверки, что порт доступен для соединения

nc -z -w 2 <server_address> <server_port> && echo yes || echo no

Опция -z проверяет, что можно установить соединение, -w 2 указывает, что нужно ждать не более 2 секунд. Если соединение устанавливается, то команда напечатает yes и no в противном случае.

READ ALSO
Не отображается конструктор и не работает отладка при Live Share

Не отображается конструктор и не работает отладка при Live Share

Если пригласить в проект Visual Studio (WPF,NET) через Live Share, конструктор макета отображается только у меня, запускать отладку тоже можно только на моем...

73
Как открыть SQL базу?

Как открыть SQL базу?

Хотелось бы подключиться к серверу (phpMyAdmin) и сделать выборку необходимых таблиц

150
Приведение списка классов к списку T

Приведение списка классов к списку T

Появилась проблемаЕсть у меня класс First

72
Что выбрать: nUnit vs xUnit?

Что выбрать: nUnit vs xUnit?

В чём разница между nUnit и xUnitnet?

163