基于c语言的UDP客户端、服务端二合一基础代码
基于c语言的UDP客户端、服务端二合一基础代码
示意图:
如果你只是单纯的接收广播以内的:
/************************************************************************************************************************************** * * * * * 组播接收 * * * * h :host 主机/本地 * to: 转换 * n :net 网络 * l :long 长整型 * s :short 短整型 * * htons:把本地字节序的一个短整型转换为网络字节序 * htonl:把本地字节序的一个长整型转换为网络字节序 * ntohs:把网络字节序的一个短整型转换为本地字节序 * ntohl:把网络字节序的一个长整型转换为本地字节序 * ***********************************************************************************************************************************/ #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> #include <errno.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip.h> #include <arpa/inet.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/udp.h> #include <stdlib.h> #include <string.h> #include <stdio.h> #include <netinet/in.h> int main(int argc, char *argv[]) { // 检查参数有效性 if (argc != 2) { fprintf(stderr, "argument is invaild ,errno:%d,%s\n", errno, strerror(errno)); exit(1); } // 1.创建UDP套接字 int udp_socket = socket(AF_INET, SOCK_DGRAM, 0); if (udp_socket == -1) { fprintf(stderr, "udp socket error,errno:%d,%s\n", errno, strerror(errno)); exit(1); } //-------------------------------------------------------------------------------------------------- // 2. 绑定服务器的端口和地址 struct sockaddr_in host_addr; memset(&host_addr, 0, sizeof(host_addr)); host_addr.sin_family = AF_INET; host_addr.sin_port = htons(atoi(argv[1])); // 使用命令行参数指定的端口 host_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 监听所有网络接口 if (bind(udp_socket, (struct sockaddr *)&host_addr, sizeof(host_addr)) == -1) { perror("bind error"); exit(1); } //-------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------- //3.设置组播地址 struct ip_mreq mreq; mreq.imr_multiaddr.s_addr = inet_addr("224.88.88.88"); // 组播地址 mreq.imr_interface.s_addr = htonl(INADDR_ANY); // 本地网络接口 setsockopt(udp_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); //-------------------------------------------------------------------------------------------------- // 4. 调用recvfrom等待接收数据 char buf[128] = {0}; struct sockaddr_in client; socklen_t client_len = sizeof(client); while (1) { int bytes_received = recvfrom(udp_socket, buf, sizeof(buf), 0, (struct sockaddr *)&client, &client_len); if (bytes_received == -1) { perror("recvfrom error"); continue; } printf("Received %d bytes from [%s]: %s\n", bytes_received, inet_ntoa(client.sin_addr), buf); bzero(buf, sizeof(buf)); } //-------------------------------------------------------------------------------------------------- return 0; }
接收+发送结合的基础代码:
/************************************************************************************************************************************** * * 字节序:数据以字节流的方式进行传输,底层都是采用二进制,字节流的顺序是由架构决定的,现在假设使用X86架构,是采用小端存储 * 网络字节序: * 本地字节序: * * 大端存储:低地址存储高字节 当数据超过1个字节的时候才需要区分大端还是小端 假设int型 0x12345678 0x12 | 0x34 | 0x56 | 0x78 * 小端存储:低地址存储低字节 当数据超过1个字节的时候才需要区分大端还是小端 假设int型 0x12345678 0x78 | 0x56 | 0x34 | 0x12 * * 设备A采用X86架构,所以设备A采用小端存储 待发送的数据 :0x12345678 * 设备B采用ARM架构,所以设备B采用大端存储 待接收的数据 :? * * 为了统一发送数据的格式,所以互联网传输的数据统一采用大端方式,为了方便开发,linux系统提供了转换的接口:htonl、htons、ntohl、ntohs * * h :host 主机/本地 * to: 转换 * n :net 网络 * l :long 长整型 * s :short 短整型 * * htons:把本地字节序的一个短整型转换为网络字节序 * htonl:把本地字节序的一个长整型转换为网络字节序 * ntohs:把网络字节序的一个短整型转换为本地字节序 * ntohl:把网络字节序的一个长整型转换为本地字节序 * ***********************************************************************************************************************************/ #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> #include <errno.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip.h> #include <arpa/inet.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/udp.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip.h> /* superset of previous */ #include <time.h> #include <pthread.h> #define MULTICAST_ADDR "224.88.88.88" //这里的宏定义是你自定义的广播组,如同聊天室需要在同一个频道 int udp_socket; //客户端任务 void *client(void *arg) { //2.向目标主机发送消息,需要设置目标端口和目标地址 char buffer[128] = {0}; struct sockaddr_in dest_addr; dest_addr.sin_family = AF_INET; //协议族,是固定的 dest_addr.sin_port = htons(9999); //服务器端口,必须转换为网络字节序 dest_addr.sin_addr.s_addr = inet_addr(MULTICAST_ADDR); //服务器地址 "192.168.64.xxx" bind(udp_socket,(struct sockaddr *)&dest_addr, sizeof(dest_addr));//绑定服务器和端口 while(1) { printf("请输入内容:"); scanf("%s",buffer); //3.发送客户端的上线时间 sendto(udp_socket,buffer,strlen(buffer),0, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); } } int main(int argc,char *argv[]) { //检查参数有效性 if (argc != 2) { fprintf(stderr, "argument is invaild ,errno:%d,%s\n",errno,strerror(errno)); exit(1); } //1.创建UDP套接字 udp_socket = socket(AF_INET, SOCK_DGRAM, 0); if (udp_socket == -1) { fprintf(stderr, "udp socket error,errno:%d,%s\n",errno,strerror(errno)); exit(1); } // 启用广播选项 //setsockopt(udp_socket, SOL_SOCKET, SO_BROADCAST, &broadcast, option_len); //getsockopt(udp_socket, SOL_SOCKET, SO_BROADCAST,(void *)&optval, &option_len); //---------------------------------------------------------------------------------------- //2.需要先绑定服务器的端口和地址 struct sockaddr_in host_addr; struct ip_mreqn mreq; host_addr.sin_family = AF_INET; //协议族,是固定的 host_addr.sin_port = htons(atoi(argv[1])); //目标端口,必须转换为网络字节序 host_addr.sin_addr.s_addr = INADDR_ANY; //目标地址 "192.168.64.xxx" 已经转换为网络字节序 INADDR_ANY bind(udp_socket,(struct sockaddr *)&host_addr, sizeof(host_addr)); //---------------------------------------------------------------------------------------- //加入多播组 mreq.imr_multiaddr.s_addr = inet_addr(MULTICAST_ADDR); mreq.imr_address.s_addr= htonl(INADDR_ANY); // 或者指定网络接口地址 mreq.imr_ifindex = 0; setsockopt(udp_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); //---------------------------------------------------------------------------------------- //创建客户端线程 pthread_t hostser; pthread_create(&hostser,NULL,client,NULL); //3.调用recvfrom等待接收数据,并且接收客户端的网络信息 char buf[128] = {0}; struct sockaddr_in client; socklen_t client_len = sizeof(client); while(1) { recvfrom(udp_socket,buf,sizeof(buf), 0 ,(struct sockaddr *) &client,&client_len); //默认会阻塞 // 输出消息内容 time_t now = time(NULL); printf("client ip is [%s] time:%s %s\n", inet_ntoa(client.sin_addr), ctime(&now),buf); bzero(buf,sizeof(buf)); } return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· [翻译] 为什么 Tracebit 用 C# 开发
· Deepseek官网太卡,教你白嫖阿里云的Deepseek-R1满血版
· DeepSeek崛起:程序员“饭碗”被抢,还是职业进化新起点?
· 2分钟学会 DeepSeek API,竟然比官方更好用!
· .NET 使用 DeepSeek R1 开发智能 AI 客户端