Проблема при использовании c сокетов в c# - PullRequest
3 голосов
/ 13 марта 2020

Я пытаюсь создать сокет, используя системные сокеты в c#.

Я сделал следующий код:

using System;
using System.Net;
using System.Runtime.InteropServices;

namespace test_socket

{
    public class Program
    {
        [DllImport("libc", EntryPoint = "socket", SetLastError = true)]
    public static extern int socket(int domain, int type, int protocol);
    //public static extern int socket(AddressFamily domain, SocketType type, ProtocolFamily protocol);

    [DllImport("libc", EntryPoint = "close", SetLastError = true)]
    public static extern int close(int handle);

    [DllImport("libc", EntryPoint = "connect", SetLastError = true)]
    public static extern int connect(int socket, sockaddr_in addr, int socklen_t);
    [StructLayout(LayoutKind.Sequential)]
    public struct sockaddr_in
    {
        public byte sin_len;
        public byte sin_family;
        public ushort sin_port;
        public uint sin_addr;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public byte[] sin_zero;
    };
        public static void Main() {
            Console.WriteLine("Hello World");
            int msock = socket(2, 1, 0); //AF_INET, SOCK_STREAM, 0
            IPAddress ipa = IPAddress.Parse("127.0.0.1");
            int sock_struct_size = Marshal.SizeOf(typeof(sockaddr_in));
            sockaddr_in sin = new sockaddr_in()
            {
                sin_len = (byte)sock_struct_size,
                sin_family = 2, //2
                sin_port = (ushort)IPAddress.HostToNetworkOrder((short)4569),
#pragma warning disable 618
                sin_addr = (uint)ipa.Address,
#pragma warning restore 618
                sin_zero = new byte[8] { 0, 0, 0, 0, 0, 0, 0, 0 }
            };


            var test_sock = connect(msock, sin, sock_struct_size);

            Console.WriteLine(test_sock);
            Console.WriteLine(Marshal.GetLastWin32Error());
        }
}
}

Я всегда получаю -1, когда пытаюсь подключить мою розетку. Конечно, я могу подключиться к порту 4569 локально:

te lnet 127.0.0.1 4569

Попытка 127.0.0.1 ... Подключена к localhost.

У меня нет Идея, что я пропустил.

Замените порт 4569 на что-то открытое, например 22 (с sh), если тестируете приведенный выше код.

Протестировано с помощью dotnetcore 3.1 и ma c os 10.15.3

Я сделал пример проекта c ++ для тестирования сокетов, он работал нормально:

// Client side C/C++ program to demonstrate Socket programming 
#include <stdio.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <unistd.h> 
#include <string.h> 
#define PORT 4569 

int main(int argc, char const *argv[]) 
{ 
    int sock = 0, valread; 
    struct sockaddr_in serv_addr; 
    char *hello = "Hello from client"; 
    char buffer[1024] = {0}; 
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
    { 
        printf("\n Socket creation error \n"); 
        return -1; 
    } 
    printf("sizeof: %lu", sizeof(serv_addr));

    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_port = htons(PORT); 

     printf("port: %hu", serv_addr.sin_port);

    // Convert IPv4 and IPv6 addresses from text to binary form 
    if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)  
    { 
        printf("\nInvalid address/ Address not supported \n"); 
        return -1; 
    } 

    uint x = serv_addr.sin_addr.s_addr;

    printf("addr: %du", x);
    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) 
    { 
        printf("\nConnection Failed \n"); 
        return -1; 
    } 
    send(sock , hello , strlen(hello) , 0 ); 
    printf("Hello message sent\n"); 
    valread = read( sock , buffer, 1024); 
    printf("%s\n",buffer ); 
    return 0; 
} 

Я проверил размер структуры и значения int для port / ip, они также соответствует

1 Ответ

1 голос
/ 19 марта 2020

@ bmigette нашел ответ, но после назначения награды за вопрос у него нет репутации, чтобы опубликовать его самому:

"[...] оказывается, что вам нужно чтобы вызвать GetLastWin32Error сразу после функции сокета [...] Пожалуйста, найдите ответ здесь для заинтересованных: pastebin.com / raw / j6w8HLgp"

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

public unsafe static void Main() {
    Console.WriteLine(" World");
    int msock = socket(AF_INET, SOCK_STREAM, 0);
    IPAddress ipa = IPAddress.Parse("127.0.0.1");
    int sock_struct_size = Marshal.SizeOf(typeof(sockaddr_in));
    in_addr ina = new in_addr();
    var adbytes = ipa.GetAddressBytes();
    ina.s_addr[0] = adbytes[0];
    ina.s_addr[1] = adbytes[1];
    ina.s_addr[2] = adbytes[2];
    ina.s_addr[3] = adbytes[3];


    sockaddr_in sin = new sockaddr_in()
    {
        sin_family = 2, //2
        sin_port = (ushort)IPAddress.HostToNetworkOrder((short)4569),

    };
    sin.sin_addr = ina; //.s_addr = (ushort)ipa.Address;

    Console.WriteLine(Marshal.SizeOf(sin));

    var test_sock =connect(msock, (sockaddr*)&sin, sock_struct_size);
    var errno = Marshal.GetLastWin32Error();
    Console.WriteLine(test_sock);
    Console.WriteLine(errno);

}

Необходимые определения структуры можно найти здесь и здесь .

...