C Windows工作站不可知地设置广播客户端的正确方法是什么?
我一直在尝试制作一个用于简单局域网通信的广播客户端,并且制作了一个具有基本数据序列化接口的相当简单的客户端和服务器。我一直在思考如何获取我正在使用的任何工作站的“定向广播”地址,以便设置聊天。我是网络新手,所以我在这方面没有很多经验。我试着查找示例,但我找到的大多数示例都不是我想要的。一切都在环回地址上工作,广播是我目前唯一的问题 我学习了这个基本思想,从中可以简短地解释广播数据包到底是什么,以及一些陷阱,比如防火墙、网络负载,也许还有一些不太明显的陷阱。然后,我通过一个更面向winsock的站点,即,增强了这方面的知识,这使它与像我这样的Windows特定程序更加相关 虽然我理解广播背后的想法,但我无法修改程序,使其与工作站无关,并将数据包从客户端广播到服务器。从我读过的几个SO问题和前面提到的Winsock常见问题中,我还发现“获取本地IP地址”的想法并不完全是黑白的。因为用户可能有几种不同的网络方式,或者您可以使用不同的地址。这是困扰我如何正确处理的主要问题 我当前用于包装此行为的函数是:C Windows工作站不可知地设置广播客户端的正确方法是什么?,c,sockets,networking,winsock,broadcast,C,Sockets,Networking,Winsock,Broadcast,我一直在尝试制作一个用于简单局域网通信的广播客户端,并且制作了一个具有基本数据序列化接口的相当简单的客户端和服务器。我一直在思考如何获取我正在使用的任何工作站的“定向广播”地址,以便设置聊天。我是网络新手,所以我在这方面没有很多经验。我试着查找示例,但我找到的大多数示例都不是我想要的。一切都在环回地址上工作,广播是我目前唯一的问题 我学习了这个基本思想,从中可以简短地解释广播数据包到底是什么,以及一些陷阱,比如防火墙、网络负载,也许还有一些不太明显的陷阱。然后,我通过一个更面向winsock的站
extern void WINAPI setup_connection( connection_data * data )
{
char host_name[128] = { 0 };
struct in_addr host_address;
struct in_addr broadcast_address;
if ( gethostname( &host_name[0], sizeof( host_name ) ) == HOST_NOT_FOUND )
{
winsock_error( "Getting host name", WSAGetLastError( ), FALSE );
destroy_winsock_data( data );
exit( 1 );
}
if ( !( data->host_info = gethostbyname( &host_name[0] ) ) )
{
winsock_error( "Getting host by name", WSAGetLastError( ), FALSE );
destroy_winsock_data( data );
exit( 1 );
}
host_address = *( ( struct in_addr * )data->host_info->h_addr );
broadcast_address.S_un.S_addr = ( host_address.S_un.S_addr & NETMASK ) | ( ~( NETMASK ) );
data->broadcast_address.sin_family = AF_INET;
data->broadcast_address.sin_port = htons( PORT );
data->broadcast_address.sin_addr = broadcast_address;
return;
}
主机名似乎是正确的,但gethostbyname显然返回了一个垃圾值。如果我试图检索返回的IP地址,它会说“地址无效”。虽然由于某种原因,send调用没有出错,但据我所知,数据包从未被发送
如果您想知道,我将套接字设置为如下方式广播:
extern int WINAPI set_socket_to_broadcast( int socket, BOOL setting )
{
char broadcast = ( setting ? '1' : '0' );
if ( setsockopt( socket, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof( char ) ) == SOCKET_ERROR )
{
winsock_error( "Setting Broadcast", WSAGetLastError( ), FALSE );
return -1;
}
return 0;
}
typedef struct connection_data
{
struct sockaddr_in broadcast_address;
struct hostent * host_info;
int socket;
} connection_data;
如果您想知道我的连接数据结构是什么,我声明如下:
extern int WINAPI set_socket_to_broadcast( int socket, BOOL setting )
{
char broadcast = ( setting ? '1' : '0' );
if ( setsockopt( socket, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof( char ) ) == SOCKET_ERROR )
{
winsock_error( "Setting Broadcast", WSAGetLastError( ), FALSE );
return -1;
}
return 0;
}
typedef struct connection_data
{
struct sockaddr_in broadcast_address;
struct hostent * host_info;
int socket;
} connection_data;
如果您需要更多详细信息,我可能会在明天检查并再次发布。这里的主要错误在于网络掩码不是常数,它是可以检索的接口属性。不要使用
gethostname()
和gethostbyname()
来检索本地IP地址。它并不总是有效,甚至可能报告虚假信息。不仅如此,它还不允许您访问子网信息,您需要这些信息来计算广播IP地址。连接到网络的每个IP适配器都有自己的IP和子网,因此必须使用与实际发送广播的适配器关联的值。使用特定于平台的API来枚举本地IP适配器。在Windows上,使用或。在基于*Nix的平台上,使用。其中任何一个都将为您提供IP和子网信息(getifaddrs()
甚至提供实际的广播IP)