bmigette
bmigette

Reputation: 79

Issue when Using c sockets in c#

I am trying to create a socket using system sockets in c#.

I've made the following code:

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());
        }
}
}

I'm always getting a -1 when trying to connect my socket. I can of course connect to port 4569 locally:

telnet 127.0.0.1 4569

Trying 127.0.0.1... Connected to localhost.

I have no idea what I've missed.

Replace the port 4569 with something that is opened, 22 (ssh) for example if testing the above code.

Tested with dotnetcore 3.1 and mac os 10.15.3

I made a sample c++ project to test sockets, it worked fine:

// 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; 
} 

I checked the struct size and int values of port/ip, they also match

Upvotes: 4

Views: 477

Answers (1)

Annosz
Annosz

Reputation: 1032

@bmigette found the answer, but after putting a bounty on the question he does not have enought reputation to post it himself:

"[...] turns out you need to call the GetLastWin32Error right after socket function [...] Please find answer here for those interested: pastebin.com/raw/j6w8HLgp"

In case the link is not available in the future, the working main function in the final solution is the following:

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);

}

The necessary struct definitions can be found here and here too.

Upvotes: 1

Related Questions