无需强制转换即可创建 sockaddr
Creating a sockaddr without casting
我想创建一个没有有趣转换的 sockaddr
结构,因为我有一个函数可以 return sockaddr
结构。但我真的不知道如何将数据从 sockaddr_in
重新打包到 sockaddr
。我正在关注 this tutorial,它显示了这样完成的
struct sockaddr_in myaddr;
memset((char *)&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
myaddr.sin_port = htons(0);
bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr);
我有一个 return 常规 sockaddr
的功能
sockaddr CreateAddress(std::string ip, uint16_t port){
sockaddr_in address = {0};
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr(ip.c_str());
address.sin_port = htons(port);
// return as sockaddr instead..
sockaddr addr = {0};
addr.sa_len = sizeof(sockaddr);
addr.sa_family = AF_INET;
// how to fill in sockaddr.sa_data?
// maybe like this?
addr.sa_data[0] = (address.sin_port >> 8) & 0xFF;
addr.sa_data[1] = (address.sin_port) & 0xFF;
addr.sa_data[2] = (address.sin_addr.s_addr >> 24) & 0xFF;
addr.sa_data[3] = (address.sin_addr.s_addr >> 16) & 0xFF;
addr.sa_data[4] = (address.sin_addr.s_addr >> 8) & 0xFF;
addr.sa_data[5] = (address.sin_addr.s_addr) & 0xFF;
return addr;
}
套接字 API 函数被构建为将 struct sockaddr *
作为参数,因为它可以接受多种套接字地址类型,即 struct sockaddr_un
用于 UNIX 域套接字,struct sockaddr_in
用于 IPv4,struct sockaddr_in6
用于 IPv6 等。struct sockaddr
类型是套接字 API(用 C 编写)实现继承的方式。
因此,这些函数实际上并不期望 struct sockaddr *
参数实际指向该类型的结构。根据套接字类型,它会在内部将其转换为正确的类型。
这意味着您应该使用 struct sockaddr_in
而不是 struct sockaddr
并在您与套接字函数交互时将这些结构的地址转换为 struct sockaddr *
。这是使用这些功能的预期方式。
您不能 return(或传递或以其他方式使用)sockaddr
结构的值; sockaddr
不是 representing/containing 数据的实际类型,而是 C 和 Unix 早期的误导遗留抽象,用于“基础 class”,实际套接字地址类型是“派生的”来自".
如果您正在编写 C++,尽管您最初将其标记为 C,但您的问题表明您应该使用自己的 class 来表示数据,该 class 公开一个 struct sockaddr *
以传递给套接字函数需要它,同时在内部使用适当的类型进行存储。但是,无论您使用的是 C 还是 C++,手动创建此类对象通常都是错误的。你应该只使用 getaddrinfo
.
我想创建一个没有有趣转换的 sockaddr
结构,因为我有一个函数可以 return sockaddr
结构。但我真的不知道如何将数据从 sockaddr_in
重新打包到 sockaddr
。我正在关注 this tutorial,它显示了这样完成的
struct sockaddr_in myaddr;
memset((char *)&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
myaddr.sin_port = htons(0);
bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr);
我有一个 return 常规 sockaddr
sockaddr CreateAddress(std::string ip, uint16_t port){
sockaddr_in address = {0};
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr(ip.c_str());
address.sin_port = htons(port);
// return as sockaddr instead..
sockaddr addr = {0};
addr.sa_len = sizeof(sockaddr);
addr.sa_family = AF_INET;
// how to fill in sockaddr.sa_data?
// maybe like this?
addr.sa_data[0] = (address.sin_port >> 8) & 0xFF;
addr.sa_data[1] = (address.sin_port) & 0xFF;
addr.sa_data[2] = (address.sin_addr.s_addr >> 24) & 0xFF;
addr.sa_data[3] = (address.sin_addr.s_addr >> 16) & 0xFF;
addr.sa_data[4] = (address.sin_addr.s_addr >> 8) & 0xFF;
addr.sa_data[5] = (address.sin_addr.s_addr) & 0xFF;
return addr;
}
套接字 API 函数被构建为将 struct sockaddr *
作为参数,因为它可以接受多种套接字地址类型,即 struct sockaddr_un
用于 UNIX 域套接字,struct sockaddr_in
用于 IPv4,struct sockaddr_in6
用于 IPv6 等。struct sockaddr
类型是套接字 API(用 C 编写)实现继承的方式。
因此,这些函数实际上并不期望 struct sockaddr *
参数实际指向该类型的结构。根据套接字类型,它会在内部将其转换为正确的类型。
这意味着您应该使用 struct sockaddr_in
而不是 struct sockaddr
并在您与套接字函数交互时将这些结构的地址转换为 struct sockaddr *
。这是使用这些功能的预期方式。
您不能 return(或传递或以其他方式使用)sockaddr
结构的值; sockaddr
不是 representing/containing 数据的实际类型,而是 C 和 Unix 早期的误导遗留抽象,用于“基础 class”,实际套接字地址类型是“派生的”来自".
如果您正在编写 C++,尽管您最初将其标记为 C,但您的问题表明您应该使用自己的 class 来表示数据,该 class 公开一个 struct sockaddr *
以传递给套接字函数需要它,同时在内部使用适当的类型进行存储。但是,无论您使用的是 C 还是 C++,手动创建此类对象通常都是错误的。你应该只使用 getaddrinfo
.