【发布时间】:2020-03-13 14:29:30
【问题描述】:
我正在尝试使用 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;
}
我检查了端口/ip的struct size和int值,它们也匹配
【问题讨论】:
-
你选择互操作有什么原因吗?对我来说似乎是在重新发明轮子。
-
你为什么不使用托管套接字?有一个 System.Net 程序集,其中包含所有这些好东西供您使用。你可以开始here。
-
嗨,原因是我正在使用需要套接字句柄的外部库:int maapi_connect(int sock, const struct sockaddr* srv, int srv_sz);
-
可以从托管的
Socket对象中获取本机句柄。也就是说,无法为您的问题提供一个好的答案,因为它缺乏一个好的minimal reproducible example 可以可靠地重现问题。很可能您只是遇到了一些网络配置问题,这对于 Stack Overflow 来说是题外话,但如果是编码错误,您需要提供必要的minimal reproducible example,以便人们可以重现和诊断您的错误。 -
我可以肯定地说这不是网络问题,因为我已经对此进行了测试并且我是一名网络工程师,但我同意这个可重现的例子。我将在星期一提供一个可用的 c++ 示例和不可用的 c# 示例