本程序主要是為了熟悉udp廣播的測試程序吃警,借鑒網(wǎng)上的程序
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <netdb.h>
#include <sys/ioctl.h>
#include <net/if.h>
#define CLIENT_PORT 8899
#define DEBUF_CHECK(X, Y) \
do{\
if (X < 0){\
perror(Y);\
printf("%s %s %d %s error\r\n", __FILE__, __func__, __LINE__, Y);\
}\
}while(0)
int main(int argc, char *argv[])
{
int ret;
struct ifreq ifr;
int iSocket = socket(AF_INET, SOCK_DGRAM, 0);
DEBUF_CHECK(iSocket, "create socket");
printf("--------------\r\n");
struct sockaddr_in server_addr;
memset((char *)&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(9999);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
printf("-------1-------\r\n");
ret = bind(iSocket, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
DEBUF_CHECK(ret , "bind error");
printf("-------2----%d---\r\n",sizeof(ifr.ifr_name));
strcpy(ifr.ifr_name, "ens33"); //Currently, only get eth0
printf("-------3-------\r\n");
ret = ioctl(iSocket, SIOCGIFBRDADDR, &ifr);
DEBUF_CHECK(ret , "ioctl error");
struct sockaddr_in broadcast_addr;
//memcpy(&broadcast_addr, (char *)&ifr->ifr_broadaddr, sizeof(struct sockaddr_in));
printf("-------3-------\r\n");
broadcast_addr.sin_family = AF_INET;
broadcast_addr.sin_port = htons(CLIENT_PORT);
printf("-------4-------\r\n");
//printf("\nBroadcast-IP: %s\r\n", inet_ntoa(broadcast_addr.sin_addr));
return 0;
}
以上程序主要用于測試ioctl函數(shù)是否正常運行牧嫉,之前定義的struct ifreq *ifr;但是沒有對ifr初始化炊汹,ioctl報錯:error not found device。為了測試簡單改為struct ifreq ifr
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#define IP_FOUND "IP_FOUND"
#define IP_FOUND_ACK "IP_FOUND_ACK"
#define IFNAME "ens33"
#define MCAST_PORT 9999
void set_broadcast(int *socket_fd, struct sockaddr_in *broadcast_addr, char *buffer)
{
int j = 0;
int ret;
int so_broadcast = 1;
struct ifreq *ifr;
struct ifconf ifc;
int iSocket = *socket_fd;
// 獲取所有套接字接口
ifc.ifc_len = sizeof(buffer);
ifc.ifc_buf = buffer;
if (ioctl(iSocket, SIOCGIFCONF, (char *) &ifc) < 0)
{
perror("ioctl-conf:");
return;
}
// //查找當(dāng)前網(wǎng)卡名
ifr = ifc.ifc_req;
// for (j = (ifc.ifc_len/sizeof(struct ifreq)); --j >= 0; ifr++)
// {
// if (!strcmp(ifr->ifr_name, "eth0"))
// {
// if (ioctl(iSocket, SIOCGIFFLAGS, (char *)ifr) < 0)
// {
// perror("ioctl-get flag failed:");
// }
// break;
// }
// }
//指定固定的網(wǎng)卡執(zhí)行
strncpy(ifr->ifr_name, IFNAME, strlen(IFNAME));
if (ioctl(iSocket, SIOCGIFBRDADDR, ifr) == -1)
{
perror("ioctl error");
return;
}
//將獲得的廣播地址復(fù)制到broadcast_addr
memcpy(broadcast_addr, (char *)&ifr->ifr_broadaddr, sizeof(struct sockaddr_in));
//設(shè)置廣播端口號
printf("\nBroadcast-IP: %s\r\n", inet_ntoa(broadcast_addr->sin_addr));
broadcast_addr->sin_family = AF_INET;
broadcast_addr->sin_port = htons(8899);
// broadcast_addr->sin_addr = inet_addr("192.168.0.255");
//默認(rèn)的套接字描述符sock是不支持廣播囚灼,必須設(shè)置套接字描述符以支持廣播
ret = setsockopt(iSocket, SOL_SOCKET, SO_BROADCAST, &so_broadcast,
sizeof(so_broadcast));
if(ret < 0)
{
perror("setsockopt error");
return;
}
}
int main(int argc, char* argv[])
{
int ret = -1;
int iSocket = -1;
int count;
struct sockaddr_in server_addr; //服務(wù)器端地址
struct sockaddr_in client_addr; //客戶端地址
struct timeval timeout;
char buffer[1024];
int client_ilen = sizeof(struct sockaddr_in);
iSocket = socket(AF_INET, SOCK_DGRAM, 0); //建立數(shù)據(jù)報套接字
if (iSocket == -1)
{
perror("iSocketet error");
return -1;
}
memset((void*)&server_addr, 0, sizeof(struct sockaddr_in));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htons(INADDR_ANY );
server_addr.sin_port = htons(MCAST_PORT);
set_broadcast(&iSocket, &client_addr, buffer);
//將地址結(jié)構(gòu)綁定到套接字上
ret = bind(iSocket, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret < 0)
{
perror("bind error");
return -1;
}
printf("bind ok\r\n");
fd_set readfd; //讀文件描述符集合
while(1)
{
timeout.tv_sec = 1000;
timeout.tv_usec = 0;
//文件描述符集合清0
FD_ZERO(&readfd);
//將套接字描述符加入到文件描述符集合
FD_SET(iSocket, &readfd);
//select偵聽是否有數(shù)據(jù)到來
ret = select(iSocket + 1, &readfd, NULL, NULL, &timeout); //偵聽是否可讀
switch(ret)
{
case -1: //發(fā)生錯誤
perror("select error:");
break;
case 0: //超時
printf("select timeout\n");
break;
default:
if (FD_ISSET(iSocket, &readfd))
{
//count = recvfrom(iSocket, buffer, 1024, 0, (struct sockaddr *)&client_addr, &client_ilen); //接收客戶端發(fā)送的數(shù)據(jù)
count = recvfrom(iSocket, buffer, 1024, 0, NULL, NULL); //接收客戶端發(fā)送的數(shù)據(jù)
printf("recv count = %d\r\n", count);
printf("\nClient connection information:\n\t IP: %s, Port: %d\n",
(char *)inet_ntoa(client_addr.sin_addr),
ntohs(client_addr.sin_port));
//將數(shù)據(jù)發(fā)送給客戶端
memcpy(buffer, IP_FOUND_ACK, strlen(IP_FOUND_ACK) + 1);
count = sendto(iSocket, buffer, strlen(buffer), 0,
(struct sockaddr *)&client_addr, client_ilen);
}
}
}
}
此程序是個簡單udp廣播發(fā)送服務(wù)器特铝,測試自動獲取網(wǎng)卡的廣播地址