UDP组播的c++实现
1 写socket的时候UDP和TCP的代码区别就是 是否有连接过程;有connect连接的代码的就是TCP,没有连接的就是UDP
以下代码是发送信息给组播地址(没有写接收代码。接收的代码就是要写个加入多播组,从多播组接收的逻辑)
参考:https://blog.csdn.net/zhizhengguan/article/details/109312144
// UDP_socket.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // #include <stdio.h> #include <stdlib.h> #if defined(_WIN32) #include <winsock2.h> #include <ws2tcpip.h> #include <iphlpapi.h> #pragma comment (lib, "Ws2_32.lib") #pragma comment(lib,"Iphlpapi.lib") #else #include <netdb.h> #include <arpa/inet.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <net/if.h> #include <netinet/in.h> #include <netinet/tcp.h> #endif // defined(_WIN32) int main() { char group_addr[16] = "224.1.3.250"; //初始化WinSock.否则socket(AF_INET, SOCK_DGRAM, 0)会一直返回-1 WSADATA WSAData; if (WSAStartup(MAKEWORD(2, 0), &WSAData) != 0) { return FALSE; } int socked = ::socket(AF_INET, SOCK_DGRAM, 0); if (socked < 0) { perror("socket failed!"); return 2; } struct sockaddr_in remote_addr; memset(&remote_addr, 0, sizeof(remote_addr)); remote_addr.sin_family = AF_INET; inet_pton(AF_INET, group_addr, &remote_addr.sin_addr.s_addr); remote_addr.sin_port = htons(25666); char buf[200] = "1234567890"; int length = 0; int i = 0; while (1) { i++; length = sendto(socked, buf, strlen(buf), 0, (struct sockaddr*)&remote_addr, sizeof(remote_addr)); printf("Send Message%s,%d\n", buf,i); } closesocket(socked); return 0; }
从多播组上拉流,要记得先加入多播组:
// UDP_socket.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // #include <stdio.h> #include <stdlib.h> #if defined(_WIN32) #include <winsock2.h> #include <ws2tcpip.h> #include <iphlpapi.h> #pragma comment (lib, "Ws2_32.lib") #pragma comment(lib,"Iphlpapi.lib") #else #include <netdb.h> #include <arpa/inet.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <net/if.h> #include <netinet/in.h> #include <netinet/tcp.h> #endif // defined(_WIN32) int main(int argc, char* argv[]) { WSADATA WSAData; if (WSAStartup(MAKEWORD(2, 0), &WSAData) != 0) { return FALSE; } int socked = socket(AF_INET, SOCK_DGRAM, 0); if (socked < 0) { perror("socket failed!"); return 2; } char group[16] = "224.1.2.3"; struct sockaddr_in local_addr; memset(&local_addr, 0, sizeof(local_addr)); local_addr.sin_family = AF_INET; local_addr.sin_addr.s_addr = htonl(INADDR_ANY); local_addr.sin_port = htons(20123); int ret = bind(socked, (struct sockaddr*)&local_addr, sizeof(local_addr)); if (ret < 0) { perror("bind failed !"); return 3; } struct ip_mreq mreq; inet_pton(AF_INET,group, &mreq.imr_multiaddr.s_addr); mreq.imr_interface.s_addr = htonl(INADDR_ANY); /* * * int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen); * param: * optname * * IP_MULTICAST_LOOP 支持多播数据回送 * * IP_ADD_MEMBERSHIP 加入多播组 * * IP_DROP_MEMBERSHIP 离开多播组 * optval * * IP_MULTICAST_LOOP 选项对应传入 unsigned int 来确认是否支持多播数据回送 * * IP_ADD_MEMBERSHIP 传入 ip_mreq * * IP_DROP_MEMBERSHIP 传入 ip_mreq * * */ ret = setsockopt(socked, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)); if (ret < 0) { perror("setsockopt failed !"); return 3; } else { printf("setsockopt success\n"); } char buf[10240]; int length = 0; struct sockaddr_in sender; socklen_t sender_len = sizeof(sender); while (true) { memset(buf, 0, sizeof(buf)); length = recvfrom(socked, buf, sizeof(buf), 0, (struct sockaddr*)&sender, &sender_len); buf[length] = '\0'; printf("%s\n", buf); } setsockopt(socked, IPPROTO_IP, IP_DROP_MEMBERSHIP, (const char*) & mreq, sizeof(mreq)); closesocket(socked); return 0; }
UDP单播的接收
源码:https://blog.csdn.net/ljjjjjjjjjjj/article/details/118944294
#include <stdio.h> #include <stdlib.h> #if defined(_WIN32) #include <winsock2.h> #include <ws2tcpip.h> #include <iphlpapi.h> #pragma comment (lib, "Ws2_32.lib") #pragma comment(lib,"Iphlpapi.lib") #else #include <netdb.h> #include <arpa/inet.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <net/if.h> #include <netinet/in.h> #include <netinet/tcp.h> #endif // defined(_WIN32) int main(void) { WSADATA wsd; // 初始化Socket的变量 SOCKET s; // 用于通信的Socket句柄 SOCKADDR_IN sRecvAddr, sSendAddr; // 分别为接收地址和发送地址 USHORT uPort = 14555; // 通信端口 CHAR szBuf[4096] = { 0 }; // 通信数据缓冲区 int nBufLen = 4096, nResult = 0, nSenderAddrSize = sizeof(sSendAddr); // 初始化Socket2.2版本 nResult = WSAStartup(MAKEWORD(2, 2), &wsd); if (nResult != NO_ERROR) { printf("WSAStartup failed:%d\n", WSAGetLastError()); return 1; } // 创建一个Socket,SOCK_DGRAM表示UDP类型 s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (s == INVALID_SOCKET) { printf("socket failed:%d\n", WSAGetLastError()); return 1; } // 填充Socket接口 sRecvAddr.sin_family = AF_INET; // 地址协议,AF_INET支持TCP和UDP sRecvAddr.sin_port = htons(uPort); // 通信端口,htons转为网络字节顺序 //INADDR_ANY转换过来就是0.0.0.0,泛指本机的意思,也就是表示本机的所有IP sRecvAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // 接收任意地址数据 // 绑定Socket至本机 nResult = bind(s, (SOCKADDR*)&sRecvAddr, sizeof(sRecvAddr)); if (nResult != 0) { printf("bind failed:%d\n", WSAGetLastError()); return 1; } printf("Waiting recv data...\n"); while (1) { // 阻塞式接收数据 nResult = recvfrom(s, szBuf, nBufLen, 0, (SOCKADDR*)&sSendAddr, &nSenderAddrSize); if (nResult == SOCKET_ERROR) { printf("recvfrom failed:%d\n", WSAGetLastError()); } else { //printf("SenderIP :%s\n", inet_ntoa(sSendAddr.sin_addr)); printf("SenderData:%d\n", nResult); } } // 关闭Socket连接 nResult = closesocket(s); if (nResult == SOCKET_ERROR) { printf("closesocket failed:%d\n", WSAGetLastError()); return 1; } // 清理Socket WSACleanup(); system("pause"); return 0; }