UDP广播的客户端和服务器端的代码设计
实验环境
linux
注意:
使用UDP广播,是客户端发送广播消息,服务器端接收消息。实际上是客户端探测局域网中可用服务器的一种手段。客户端发送,服务器端接收,千万不能弄混淆!!!
为了避免混淆,本文不使用client、server字眼。而使用send,recv
构建send_broadcast.c。发送广播消息,并打印接收端的IP和端口,退出时发送"done"消息
流程:创建一个socket,并用setscokopt函数声明这是一个broadcast类型的socket,然后通过这个socket向INADDR_BROADCAST("255.255.255.255")发送消息。
#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #define PORT 1234 #define BUFFER_SIZE 100 int32_t main() { char msg[BUFFER_SIZE] = "I am a broadcast message"; int32_t nb = 0; struct sockaddr_in addrto; int32_t nlen=sizeof(addrto); int32_t sockfd = -1; if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { perror("create socket failed\n"); return -1; } const int opt = 1; //设置该套接字为广播类型, nb = setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST | SO_REUSEADDR, &opt, sizeof(opt)); if(nb == -1) { perror("set socket error...\n"); return -1; } /**< 接收者地址结构 */ bzero(&addrto, sizeof(struct sockaddr_in)); addrto.sin_family = AF_INET; addrto.sin_addr.s_addr = htonl(INADDR_BROADCAST); addrto.sin_port = htons(PORT); int ret = sendto(sockfd, msg, BUFFER_SIZE, 0, (struct sockaddr*)&addrto, nlen); if (ret < 0) { perror("send error.\n"); } /**< 打印接收者的IP和端口号 */ printf("recver's ip is %s, port is %d.\n", inet_ntoa(addrto.sin_addr), htons(addrto.sin_port)); bzero(msg, BUFFER_SIZE); memcpy(msg, "done", 5); sendto(sockfd, msg, BUFFER_SIZE, 0, (struct sockaddr*)&addrto, nlen); printf("Done\n"); return 0; }
构建recv_broadcast.c 接收广播消息,打印发送端的IP和端口号,在接收到done后停止并退出
流程:创建一个socket并绑定INADDR_ANY的本地地址,接收消息
#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #define PORT 1234 #define BUFFER_SIZE 100 int32_t main() { struct sockaddr_in addrto; struct sockaddr_in from; int32_t listenfd = -1; int32_t len = sizeof(from); char recvbuf[BUFFER_SIZE]; if ((listenfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { perror("create socket failed\n"); return -1; } bzero(&addrto, sizeof(struct sockaddr_in)); bzero(&from, sizeof(struct sockaddr_in)); addrto.sin_family = AF_INET; addrto.sin_port = htons(PORT); addrto.sin_addr.s_addr = htonl(INADDR_ANY); const int opt = 1; int32_t nb = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); if(nb == -1) { perror("set socket error...\n"); return -1; } /**< 绑定自己的地址 */ if (bind(listenfd, (struct sockaddr *)&addrto, len) == -1) { perror("bind error\n"); return -1; } while (1) { //从广播地址接收消息 int ret = recvfrom(listenfd, recvbuf, BUFFER_SIZE, 0, (struct sockaddr*)&from, &len); if (ret > 0) { recvbuf[ret] = '\0'; printf("receive messgse:%s\n", recvbuf); if (!strcmp("done", recvbuf)) { break; } } else { perror("recv error.\n"); } bzero(recvbuf, BUFFER_SIZE); /**< 打印发送者的ip和端口号 */ printf("sender's ip is %s, port is %d.\n", inet_ntoa(from.sin_addr), htons(from.sin_port)); } close(listenfd); printf("Done\n"); return 0; }
Makefile
all:sender recver sender: gcc send_broadcast.c -o sender recver: gcc recv_broadcast.c -o recver clean: rm -rf sender recver