udp可以进行广播,但是有多个网卡的时候如何让多个网卡同时发送广播?有人说在bind的时候,指定“addrClient.sin_addr.s_addr = INADDR_ANY”,但是这样就真的行了吗?如果有人测试后就会发现这样依然不是所有的网卡同时发送广播,下面给出了一种方式,主要是采用每一个网卡绑定一个socket,然后每个socket都同时进行广播;
如果不清楚udp单网卡如何通讯的,不知道服务器的代码怎么弄的可以给我留言,谢谢!
方便他人亦是方便自己,如果觉得还行就点下赞吧,这样可以帮助其他人更快的找到解决问题的方法;有疑问的也可留言哦, 谢谢!
源代码链接: https://pan.baidu.com/s/1rblrwzP_bK5HCNfMyGVwfQ 提取码: nwus
客户端完整代码:
#include <stdio.h>
#include <winsock.h>
#include <time.h>
#pragma comment(lib,"ws2_32.lib")
DWORD WINAPI ThreadProc(_In_ LPVOID lpParameter)
{
char szIp[16] = {0};
strcpy (szIp, (char*)lpParameter);
SOCKET sockClient = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (SOCKET_ERROR == sockClient)
{
printf ("socket create failed. ip=[%s] errno=[%d] ", szIp, WSAGetLastError());
return -2;
}
BOOL bBroadcast = TRUE;
if (0 != setsockopt ( sockClient,SOL_SOCKET,SO_BROADCAST, (CHAR *)&bBroadcast, sizeof(BOOL)))
{
printf ("setsockopt failed. ip=[%s] errno=[%d]", szIp, WSAGetLastError());
return -3;
}
SOCKADDR_IN addrClient = {0};
addrClient.sin_family = AF_INET;
addrClient.sin_addr.s_addr = inet_addr(szIp);
addrClient.sin_port = 0; /// 0 表示由系统自动分配端口号
if (0 != bind (sockClient, (sockaddr*)&addrClient, sizeof(addrClient)))
{
printf ("bind failed.ip=[%s] errno=[%d]\n", szIp, WSAGetLastError());
}
SOCKADDR_IN addrServer = {0};
addrServer.sin_family = AF_INET;
addrServer.sin_addr.s_addr = htonl ( INADDR_BROADCAST );
addrServer.sin_port = htons (10001);
int nConunter = 0;
while(1)
{
char pcSendMsg[UCHAR_MAX] = {0};
time_t rawTime;
time(&rawTime);
tm *t = localtime(&rawTime);
sprintf(pcSendMsg, "%04d-%02d-%02d %02d-%02d-%02d | ip=[%s]", t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, szIp);
sendto ( sockClient, pcSendMsg, strlen(pcSendMsg)+1, 0, (SOCKADDR *) &addrServer, sizeof ( SOCKADDR_IN ));
printf("%s\n",pcSendMsg);
Sleep(1000);
}
closesocket(sockClient);
return 0;
}
int main()
{
WSADATA wsaData = {0};
if(0 != WSAStartup(MAKEWORD( 2, 2 ), &wsaData ))
{
printf("WSAStartup failed.errno=[%d]", WSAGetLastError());//初始化失败返回-1
return -1;
}
char hostname[1024] = {0};
gethostname(hostname, sizeof(hostname)); //获得本地主机名
PHOSTENT hostinfo = gethostbyname(hostname);//信息结构体
while(*(hostinfo->h_addr_list) != NULL) //输出IP地址
{
char* ip = inet_ntoa(*(struct in_addr *) *hostinfo->h_addr_list);
CreateThread(NULL, 0, ThreadProc, ip, 0, 0);
Sleep(100);
hostinfo->h_addr_list++;
}
Sleep(INFINITE);
WSACleanup();
return 0;
}
一、main函数中,打开网络模块:
WSADATA wsaData = {0};
if(0 != WSAStartup(MAKEWORD( 2, 2 ), &wsaData ))
{
printf("WSAStartup failed.errno=[%d]", WSAGetLastError());//初始化失败返回-1
return -1;
}
获取本地主机名称:
char hostname[1024] = {0};
gethostname(hostname, sizeof(hostname)); //获得本地主机名
通过主机名称,遍历计算机上的所有的网卡,并将网卡的ip创建线程回调函数
PHOSTENT hostinfo = gethostbyname(hostname);//信息结构体
while(*(hostinfo->h_addr_list) != NULL) //输出IP地址
{
char* ip = inet_ntoa(*(struct in_addr *) *hostinfo->h_addr_list);
CreateThread(NULL, 0, ThreadProc, ip, 0, 0);
Sleep(100);
hostinfo->h_addr_list++;
}
二、ThreadProc 线程回调函数
记录一个网卡对应的ip地址
char szIp[16] = {0};
strcpy (szIp, (char*)lpParameter);
创建一个udp socket:
SOCKET sockClient = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (SOCKET_ERROR == sockClient)
{
printf ("socket create failed. ip=[%s] errno=[%d] ", szIp, WSAGetLastError());
return -2;
}
将socket 同网卡(ip)绑定,端口给0,交由系统随机分配:
SOCKADDR_IN addrClient = {0};
addrClient.sin_family = AF_INET;
addrClient.sin_addr.s_addr = inet_addr(szIp);
addrClient.sin_port = 0; /// 0 表示由系统自动分配端口号
if (0 != bind (sockClient, (sockaddr*)&addrClient, sizeof(addrClient)))
{
printf ("bind failed.ip=[%s] errno=[%d]\n", szIp, WSAGetLastError());
}
消息循环发送消息
while(1)
{
char pcSendMsg[UCHAR_MAX] = {0};
time_t rawTime;
time(&rawTime);
tm *t = localtime(&rawTime);
sprintf(pcSendMsg, "%04d-%02d-%02d %02d-%02d-%02d | ip=[%s]", t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, szIp);
sendto ( sockClient, pcSendMsg, strlen(pcSendMsg)+1, 0, (SOCKADDR *) &addrServer, sizeof ( SOCKADDR_IN ));
printf("%s\n",pcSendMsg);
Sleep(1000);
}
关闭socketclosesocket(sockClient);