Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从unix套接字读取字节并用c打印ip地址_C_Unix Socket - Fatal编程技术网

从unix套接字读取字节并用c打印ip地址

从unix套接字读取字节并用c打印ip地址,c,unix-socket,C,Unix Socket,我有一个Java客户机和一个通过unix套接字进行通信的C服务器。 我想从客户端向服务器发送一个ip地址。在服务器端,当我尝试解释从客户端接收到的字节时,我得到了正确的[01],但当我将ip\U地址打印到视频时,我得到了0.0.0。我做错了什么?我想我用了一种错误的方式来表达这个地址。我需要实现IPv4映射的IPv6地址,这就是为什么我使用sockaddr\u存储,这是最常见的情况 以下是我的一些代码摘录: Java客户端执行以下操作: OutputStream out; byte[]

我有一个Java客户机和一个通过unix套接字进行通信的C服务器。 我想从客户端向服务器发送一个ip地址。在服务器端,当我尝试解释从客户端接收到的字节时,我得到了正确的
[01]
,但当我将ip\U地址打印到视频时,我得到了
0.0.0
。我做错了什么?我想我用了一种错误的方式来表达这个地址。我需要实现IPv4映射的IPv6地址,这就是为什么我使用
sockaddr\u存储
,这是最常见的情况

以下是我的一些代码摘录:

Java客户端执行以下操作:

OutputStream out;    
byte[] ipAddress = Inet6Address.getByName("1.1.1.1").getAddress();
out.write(ipAddress);
C服务器执行以下操作:

    struct sockaddr_storage * ip_address;
    n = read(rcv_sock, msg, PSIZE);
    printf("I recevied n bytes: %d\n", n);// i get 4 bytes
    print_bytes(msg, n);
    ip_address = (union sockaddr_storage *)msg;
    char str[INET_ADDRSTRLEN];
    inet_ntop(AF_INET, &(ip_address->__ss_padding), str, INET_ADDRSTRLEN);
    printf("ip_address = %s\n", str); //i get 0.0.0.0
特别是,服务器需要包含28字节长的头+套接字地址结构的消息。我已成功正确解码了头,但没有正确解码套接字地址结构。

TCPv4(TCP/IPv4)套接字由32位地址和16位端口号标识。TCPv6(TCP/IPv6)套接字由128位地址和16位端口号标识。
sockaddr\uu
结构的内部信息比C库内部使用(和需要)的信息多得多。您不能将这些结构从一个系统转移到另一个系统,而期望它们工作。(或者在另一端做出某种意义上的判断,真的。)

是IPv6地址,前80位为零,后16位为1,后32位为IPv4地址。它们通常以IPv6格式编写为
::ffff:a.b.c.d
,其中
a.b.c.d
是映射到IPv6的IPv4地址

与其让客户端发送任何类型的“sockaddr结构”,它肯定应该发送128位IPv6地址,可能还有16位端口号。如果您以二进制格式发送这些数据,通常的做法是以网络字节顺序传输这些数据,即先传输最高有效字节

但是,我认为将这些作为字符串发送更简单、更可靠,例如,使用format
IPv6
\0
\0
(即在地址后添加一个零字节,在端口后添加另一个零字节)。这样,您只需要一个指向地址(
node
)的指针和一个指向端口(
serv
)的指针,就可以使用重构所需的
sockaddr\u in6
结构


如果您必须以二进制形式发送地址和端口(例如,为了确保初始数据包大小固定),理论上您可以手工构造结构。然而,这是特定于体系结构(字节顺序敏感)的,并且是脆弱的。将IPv6地址转换为字符串(如果IPv4已映射,则转换为
::ffff:a.b.c.d
,或者将端口转换为十进制数,
aaaa:bbbbbb:cccc:dddddd:eeee:ffff:gggggg:hhh>)要简单得多,然后再次使用以从中获取合适的套接字结构。

为什么您会假设Java Inet6Address的字节表示是C
struct sockaddr\u存储
?如果01010101数据是您想要接收的数据,那么就不需要将其包装到任何类型的sockaddr中,也不需要进行任何偏移。按照c服务器代码的文档将消息按原样传递给inet_ntop。它需要一个特定的头+一个套接字地址结构。我设法制作了标题,但我似乎无法正确地发送地址结构。@用户,你能告诉我你想要什么吗mean@Pheonix7你能链接我们或提供C服务器的文档吗?因为按原样,C服务器可能希望在
中传递一个
sockaddr\u或类似的消息。在我的书中,这是一个坏主意,导致在快车道上出现不可移植和未定义的行为。在任何情况下,“header”都是
sockaddr
中的
ss_family
字段。我发现getaddrinfo()是发送ip信息的最佳方式,但从文档中看,它似乎是针对网络pk的,而不是针对本地unix套接字的。如何设置参数以进行本地通信结束我的特定标头+此addrinfo类型?您的问题表明您希望传输IPv4/IPv6地址(可能还有端口号)。你用来传递信息的方法并不重要。如果客户端和服务器使用进行通信,则它们可以将套接字描述符作为辅助消息进行传输。这在C语言中非常容易,但我认为Java不支持它(除非您有一个本机库来使用它)。我使用的是JUDS,但它似乎不支持序列化假设你参考了这篇文章,它表明它不支持传递描述符(
SCM\u RIGHTS
associative messages)。哦,不。我发现JUDS的唯一其他替代方法是JUnitSocket。您知道它是否支持传递描述符吗?这可能是我照顾的工作吗?谢谢你的帮助