本程序主要是为了熟悉udp广播的测试程序,借鉴网上的程序
#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函数是否正常运行,之前定义的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;
}
// //查找当前网卡名
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;
// }
// }
//指定固定的网卡执行
strncpy(ifr->ifr_name, IFNAME, strlen(IFNAME));
if (ioctl(iSocket, SIOCGIFBRDADDR, ifr) == -1)
{
perror("ioctl error");
return;
}
//将获得的广播地址复制到broadcast_addr
memcpy(broadcast_addr, (char *)&ifr->ifr_broadaddr, sizeof(struct sockaddr_in));
//设置广播端口号
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");
//默认的套接字描述符sock是不支持广播,必须设置套接字描述符以支持广播
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; //服务器端地址
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); //建立数据报套接字
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);
//将地址结构绑定到套接字上
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侦听是否有数据到来
ret = select(iSocket + 1, &readfd, NULL, NULL, &timeout); //侦听是否可读
switch(ret)
{
case -1: //发生错误
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); //接收客户端发送的数据
count = recvfrom(iSocket, buffer, 1024, 0, NULL, NULL); //接收客户端发送的数据
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));
//将数据发送给客户端
memcpy(buffer, IP_FOUND_ACK, strlen(IP_FOUND_ACK) + 1);
count = sendto(iSocket, buffer, strlen(buffer), 0,
(struct sockaddr *)&client_addr, client_ilen);
}
}
}
}
此程序是个简单udp广播发送服务器,测试自动获取网卡的广播地址
网友评论