powered by simpleCommunicator - 2.0.56     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Номер TCP порта по имени?
10 сообщений из 10, страница 1 из 1
Номер TCP порта по имени?
    #38359831
spam19701
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Есть ли какой-нибудь стандартный способ получить номер порта, если известно имя службы (т.е. соответствие из файла system32\drivers\etc\services) или наоборот, имя службы по номеру порта? Но так, чтобы не писать обёртки для виндовых DLL и не читать содержимое этого файла напрямую?
...
Рейтинг: 0 / 0
Номер TCP порта по имени?
    #38359877
Arm79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а если я напишу свою службу, то как определить какой порт она прослушивает? И что делать, если одна служба прослушивает несколько портов?
...
Рейтинг: 0 / 0
Номер TCP порта по имени?
    #38359888
carrotik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...вот тут, как сам автор признает, корявый велосипед с использованием парсинга netstat и WMI ....
http://dobrzanski.net/2012/01/09/how-to-get-service-name-listening-at-specific-port-number/
...
Рейтинг: 0 / 0
Номер TCP порта по имени?
    #38360463
spam19701
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Я смотрю, обсуждение ушло немного в другую сторону, я же не это спрашивал. Ладно, упростим вопрос. Нарыл вот такой пример (и он работает):

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
    const int WSADESCRIPTION_LEN = 257;
    const int WSASYS_STATUS_LEN = 128;
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct WSAData
    {
      public ushort wVersion;
      public ushort wHighVersion;
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = WSADESCRIPTION_LEN + 1)]
      public string szDescription;
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = WSASYS_STATUS_LEN + 1)]
      public string szSystemStatus;
      ushort iMaxSockets;
      ushort iMaxUdpDg;
      [MarshalAs(UnmanagedType.LPStr)]
      string lpVendorInfo;
    };

    unsafe public struct servent
    {
      public char* s_name;
      public char** s_aliases;
      public ushort s_port;
      public char* s_proto;
    };

    [DllImport("ws2_32.dll", SetLastError = true)]
    static extern ushort htons(ushort hostshort);

    [DllImport("ws2_32.dll", SetLastError = true)]
    unsafe static extern servent* getservbyname(string name, string proto);

    [DllImport("ws2_32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern int WSAStartup(ushort wVersionRequested, out WSAData lpWSAData);

    [DllImport("ws2_32.dll", SetLastError = true)]
    public static extern int WSACleanup();

    unsafe static ushort GetPortByName(string PortName, string PortType)
    {
      servent* ServEnt = getservbyname(PortName, PortType);
      if (ServEnt != null)
        return htons(ServEnt->s_port);
      return 0;
    }

    private void button1_Click(object sender, EventArgs e)
    {
      WSAData D;
      if (WSAStartup(0x101, out D) == 0) 
      {
        try
        {
          int Port = GetPortByName("ftp", "tcp");
          MessageBox.Show("Port = " + Port); //Порт 21
        }
        finally
        {
          WSACleanup();
        }
      }
    }



Так вот. У меня вопрос - можно ли обойтись без DllImport? Или хотя бы сделать так, чтобы в свойствах проекта не надо было указывать "Разрешить небезопасный код" (unsafe), если уж без обёрток не обойтись?
...
Рейтинг: 0 / 0
Номер TCP порта по имени?
    #38360479
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
spam19701У меня вопрос - можно ли обойтись без DllImport
нет

spam19701Или хотя бы сделать так, чтобы в свойствах проекта не надо было указывать "Разрешить небезопасный код" (unsafe), если уж без обёрток не обойтись?
да. getservbyname должа возвратить IntPtr, структуру servent сделать безопасной, указатели в ней не нужны - заменить на IntPtr, получить структуру из указателя, возвращённого getservbyname - Marshal.PtrToStructure
...
Рейтинг: 0 / 0
Номер TCP порта по имени?
    #38361816
spam19701
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо, убрать unsafe получилось:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
    [StructLayout(LayoutKind.Sequential)]
    public struct servent
    {
      public IntPtr s_name;    //public char* s_name;
      public IntPtr s_aliases; //char** s_aliases;
      public ushort s_port;
      public IntPtr s_proto; //char* s_proto;
    };

    [DllImport("ws2_32.dll", SetLastError = true)]
    static extern IntPtr getservbyname(string name, string proto);

    static ushort GetPortByName(string PortName, string PortType)
    {
      IntPtr ptr = getservbyname(PortName, PortType);
      if (ptr != null)
      {
        servent ServEnt = (servent)Marshal.PtrToStructure(ptr, typeof(servent));
        return htons(ServEnt.s_port);
      }
      return 0;
    }



Только вот какой вопрос у меня возник (хотя в данном случае мне это не надо, но чисто с познавательной целью)

Если мне надо было бы обратиться к s_name, я бы наверно написал так: Marshal.PtrToStringAnsi(ServEnt.s_name);

А что если бы мне надо было бы обратиться к какому-то элементу s_aliases (это ж, я так понимаю, указатель на начало массива указателей на строки). Как мне, к примеру, обратиться к 3-й строке, при таком моём описании структуры?
...
Рейтинг: 0 / 0
Номер TCP порта по имени?
    #38362281
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
spam19701Если мне надо было бы обратиться к s_name, я бы наверно написал так: Marshal.PtrToStringAnsi(ServEnt.s_name);
Можно и так, но маршаллер справится самостоятельно -

public string s_proto; //char* s_proto; -этого достаточно

spam19701А что если бы мне надо было бы обратиться к какому-то элементу s_aliases
например так -
Код: c#
1.
2.
3.
4.
5.
6.
7.
                IntPtr p = ServEnt.s_aliases;                
                int ofs=0;
                IntPtr ps;
                while(IntPtr.Zero != ( ps = Marshal.ReadIntPtr(p, ofs))){
                    string s = Marshal.PtrToStringAnsi(ps);
                    ofs +=  Marshal.SizeOf(typeof(IntPtr));
                }



Предупреждение! в 32 и 64 битах структура servent имеет разный порядок полей!
для x64 -
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
[StructLayout(LayoutKind.Sequential)]
    public struct servent
    {
        public string s_name;    //public char* s_name;
        public IntPtr s_aliases; //char** s_aliases;
        public string s_proto; //char* s_proto;
        public ushort s_port;
    };
...
Рейтинг: 0 / 0
Номер TCP порта по имени?
    #38362428
spam19701
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ИзопропилПредупреждение! в 32 и 64 битах структура servent имеет разный порядок полей!

Вот те раз... Час от часу не легче. Интересно, зачем это понадобилось Microsoft - чтоб всех запутать? :-)

И как же в таких случаях правильно поступать? Нет ли у JIT - компилятора какого-нибудь аналога условной компиляции, чтобы он в зависимости от разрядности проги перевёл в машинный код либо тот, либо другой кусок во время старта? Или придётся только в программе анализировать разрядность этого пресловутого IntPtr, и в зависимости от нее вызывать ту или иную функцию, которая будет использовать соответственно ту или иную структуру? Как-то совсем не кузяво. А там, смотришь, и 128 разрядов не за горами, там опять свои структуры небось :-) Потому и хотелось бы обходиться без обёрток, но "родные" средства есть не для всего...

Интересно, и много ль ещё таких структур, которые имеют другой порядок полей?
...
Рейтинг: 0 / 0
Номер TCP порта по имени?
    #38362456
spam19701
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вот такая фигня что ль получится?
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
    [StructLayout(LayoutKind.Sequential)]
    public struct servent32
    {
      public string s_name;    //public char* s_name;
      public IntPtr s_aliases; //char** s_aliases;
      public ushort s_port;
      public string s_proto; //char* s_proto;
    };

    [StructLayout(LayoutKind.Sequential)]
    public struct servent64
    {
      public string s_name;    //public char* s_name;
      public IntPtr s_aliases; //char** s_aliases;
      public string s_proto; //char* s_proto;
      public ushort s_port;
    };

    static ushort GetPortByName(string PortName, string PortType)
    {
      ushort Result = 0;
      WSAData D;
      if (WSAStartup(0x101, out D) == 0) 
      {
        try
        {
          IntPtr ptr = getservbyname(PortName, PortType);
          if (ptr != null)
          {
            int Bits = Marshal.SizeOf(typeof(IntPtr)) * 8; 
            switch (Bits)
            {
              case 32:
                servent32 ServEnt32 = (servent32)Marshal.PtrToStructure(ptr, typeof(servent32));
                Result = htons(ServEnt32.s_port);
                break;
              case 64:
                servent64 ServEnt64 = (servent64)Marshal.PtrToStructure(ptr, typeof(servent64));
                Result = htons(ServEnt64.s_port);
                break;
              default:
                throw new Exception(Bits + "-bit operating system is not supported yet");
            }
          }
        }
        finally
        {
          WSACleanup(); 
        }
      }
      return Result;
    }


Или можно как-нибудь попроще и покрасивее?
...
Рейтинг: 0 / 0
Номер TCP порта по имени?
    #38362508
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
spam19701Вот те раз... Час от часу не легче. Интересно, зачем это понадобилось Microsoft - чтоб всех запутать? :-)
Для c/c++ - не имеет значения, исходили из желания выровнять поля

spam19701Нет ли у JIT - компилятора какого-нибудь аналога условной компиляции, чтобы он в зависимости от разрядности проги перевёл в машинный код либо тот, либо другой кусок во время старта?
это решается подключением сборок собраных под тот или иной режим (как управляемых так и нативных dll)

spam19701Интересно, и много ль ещё таких структур, которые имеют другой порядок полей?
насколько я знаю - немного, но при написании P/Invoke имеет смысл заглядывать в .h файлы.
В документации может быть не описано(как в случае servent)
spam19701Вот такая фигня что ль получится?
почти :)
WSAStartup - эту хрень лучше не вызывать самому , достаточно обратиться предварительно к любому сокетному объекту ( new TcpListener() например вызвать)

вариант говнокода :
Код: c#
1.
2.
3.
4.
		PortableExecutableKinds pek;
                ImageFileMachine ifm;
                Assembly.GetExecutingAssembly().GetModules()[0].GetPEKind(out pek,out ifm);
                int x = Marshal.ReadInt16(ptr, ifm == ImageFileMachine.I386? 8 : 24);
...
Рейтинг: 0 / 0
10 сообщений из 10, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Номер TCP порта по имени?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]