c# - 在 c# 中使用 c 套接字时出现的问题

标签 c# sockets interop libc

我正在尝试使用 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:
远程登录 127.0.0.1 4569
正在尝试 127.0.0.1 ...
连接到本地主机。
我不知道我错过了什么。
如果测试上述代码,请将端口 4569 替换为已打开的端口,例如 22 (ssh)。
使用 dotnetcore 3.1 和 mac 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; 
} 
我检查了 port/ip 的 struct size 和 int 值,它们也匹配

最佳答案

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

}

必要的结构定义也可以在 herehere 中找到。

关于c# - 在 c# 中使用 c 套接字时出现的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60672282/

相关文章:

php - PHP中的stream_socket_server是否用于创建生产服务器?

C# 项目 2010,在其他计算机上的独立可执行文件

silverlight - 如何在 Silverlight 4 中释放 COM 对象

c# - 在 ajax 成功中使用模型数据

c# - GroupBy 选择的 LINQ 错误 : System. NotSupportedException

c# - 如何在 C# 中将消息框显示为系统模式?

c# - 使用c#从doc文件中检索表数据

c# - 如何创建类的常量静态不可变实例?

c - Web 服务器未收到所有请求

java - Perl Pipe 不重定向 Java 进程输出