zoukankan      html  css  js  c++  java
  • UDP组播相关

    Windows服务端

    #include "stdafx.h"
    
    
    #include <winsock2.h> 
    #include <ws2tcpip.h> 
    #include <stdio.h> 
    #include <stdlib.h> 
    #define MCASTADDR "239.255.255.239" //本例使用的多播组地址。 
    #define MCASTPORT 9111 //绑定的本地端口号。 
    #define BUFSIZE 1024 //接收数据缓冲大小。
    #pragma comment(lib,"Ws2_32.lib.")
    
    int main( int argc,char ** argv) 
    {
    	WSADATA wsd; 
    
    	struct sockaddr_in local,remote,from; 
    	SOCKET sock,sockM; 
    	char recvbuf[BUFSIZE]; 
    	int len = sizeof( struct sockaddr_in); 
    	int ret; //初始化WinSock2.2 
    	if( WSAStartup( MAKEWORD(2,2),&wsd) != 0 ) 
    	{ 
    		printf("WSAStartup() failed
    "); return -1; 
    	} 
        if((sock=WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0, WSA_FLAG_MULTIPOINT_C_LEAF|WSA_FLAG_MULTIPOINT_D_LEAF| WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
    	{ 
    		printf("socket failed with:%d
    ",WSAGetLastError());
    	    WSACleanup(); 
    		return -1; 
    	} 
    	//将sock绑定到本机某端口上。 
    	local.sin_family = AF_INET; 
    	local.sin_port = htons(MCASTPORT); 
    	local.sin_addr.s_addr = INADDR_ANY; 
    	if( bind(sock,(struct sockaddr*)&local,sizeof(local)) == SOCKET_ERROR ) 
    	{
    		printf( "bind failed with:%d 
    ",WSAGetLastError()); 
    		closesocket(sock); 
    		WSACleanup();
    		return -1; 
    	} //加入多播组 
    	remote.sin_family = AF_INET; 
    	remote.sin_port = htons(MCASTPORT); 
    	remote.sin_addr.s_addr = inet_addr( MCASTADDR ); 
    	if(( sockM = WSAJoinLeaf(sock,(SOCKADDR*)&remote,sizeof(remote), NULL,NULL,NULL,NULL, JL_BOTH)) == INVALID_SOCKET) 
    	{ 
    		printf("WSAJoinLeaf() failed:%d
    ",WSAGetLastError()); 
    		closesocket(sock);
    		WSACleanup();
    		return -1; 
    	} //接收多播数据,当接收到的数据为"QUIT"时退出。 
    	while(1) 
    	{ 
    		if(( ret = recvfrom(sock,recvbuf,BUFSIZE,0, (struct sockaddr*)&from,&len)) == SOCKET_ERROR) 
    		{ 
    			printf("recvfrom failed with:%d
    ",WSAGetLastError()); 
    			closesocket(sockM); 
    			closesocket(sock); 
    			WSACleanup(); 
    			return -1; 
    		} if( strcmp(recvbuf,"QUIT") == 0 )
    			break; 
    		else { 
    			recvbuf[ret] = ''; 
    			printf("RECV:' %s ' FROM <%s> 
    ",recvbuf,inet_ntoa(from.sin_addr));
    		} 
    	} 
    	closesocket(sockM); 
    	closesocket(sock); 
    	WSACleanup(); 
    	return 0; 
    }
    

      

    windows客户端

    #include "stdafx.h"
    
    
    #include <stdio.h>  
    #include <winsock2.h>  
    #include <ws2tcpip.h>  
    #pragma comment(lib, "ws2_32.lib")  
    
    int main()  
    {  
    	WSADATA wsaData;  
    	WSAStartup(MAKEWORD(2, 2), &wsaData);     
    
    	SOCKET sock = socket(AF_INET,SOCK_DGRAM,0);  
    
    	sockaddr_in my;  
    	my.sin_family = AF_INET;  
    	//my.sin_addr.S_un.S_addr = inet_addr("192.168.199.133"); 
    	my.sin_addr.S_un.S_addr=INADDR_ANY;
    	my.sin_port = htons(56789);  
    
    	bind(sock, (sockaddr*)&my, sizeof(my));
    
    
    
    	int n = 1; // 注意, 这个n值很重要, 下面我会讲到  
    	setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&n, sizeof(n));  
    
    	sockaddr_in addr;  
    	addr.sin_addr.S_un.S_addr = inet_addr("239.255.255.239");  
    	addr.sin_family = AF_INET;  
    	addr.sin_port = htons(9111);  
    
    	static int i = 0;  
    	while(1)  
    	{     
    		char buf[100] = {0};  
    		sprintf_s(buf, "blablablabla:%d", i++);  
    		sendto(sock, buf, strlen(buf) + 1, 0, (sockaddr*)&addr, sizeof(sockaddr));  
    		Sleep(500);   
    	}  
    
    	closesocket(sock);  
    	WSACleanup();  
    
    	return 0;  
    }  
    

      

    Linux服务端

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <netdb.h>
    #include <errno.h>
    
    #define BUFLEN 255
    /*********************************************************************
    *filename: mcastserver.c
    *purpose: 演示组播编程的基本步骤,组播服务器端,关键在于加入组
    *tidied by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com)
    Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言
    *date time:2007-01-25 13:20:00
    *Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途
    * 但请遵循GPL
    *Thanks to: Google.com
    *Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力
    * 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!
    *********************************************************************/
    int main(int argc, char **argv)
    {
    struct sockaddr_in peeraddr;
    struct in_addr ia;
    int sockfd;
    char recmsg[BUFLEN + 1];
    unsigned int socklen, n;
    struct hostent *group;
    struct ip_mreq mreq;
    
    /* 创建 socket 用于UDP通讯 */
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
    printf("socket creating err in udptalk
    ");
    exit(1);
    }
    
    /* 设置要加入组播的地址 */
    bzero(&mreq, sizeof(struct ip_mreq));
    if (argv[1]) {
        if ((group = gethostbyname(argv[1])) == (struct hostent *) 0) {
            perror("gethostbyname");
            exit(errno);
        }
    } else {
        printf
            ("you should give me a group address, 224.0.0.0-239.255.255.255
    ");
        exit(errno);
    }
    
    bcopy((void *) group->h_addr, (void *) &ia, group->h_length);
    /* 设置组地址 */
    bcopy(&ia, &mreq.imr_multiaddr.s_addr, sizeof(struct in_addr));
    
    /* 设置发送组播消息的源主机的地址信息 */
    mreq.imr_interface.s_addr = htonl(INADDR_ANY);
    
    /* 把本机加入组播地址,即本机网卡作为组播成员,只有加入组才能收到组播消息 */
    if (setsockopt
            (sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,
             sizeof(struct ip_mreq)) == -1) {
        perror("setsockopt");
        exit(-1);
    }
    
    socklen = sizeof(struct sockaddr_in);
    memset(&peeraddr, 0, socklen);
    peeraddr.sin_family = AF_INET;
    if (argv[2])
        peeraddr.sin_port = htons(atoi(argv[2]));
        else
        peeraddr.sin_port = htons(7838);
        if (argv[1]) {
            if (inet_pton(AF_INET, argv[1], &peeraddr.sin_addr) <= 0) {
                printf("Wrong dest IP address!
    ");
                exit(0);
            }
        } else {
            printf("no group address given, 224.0.0.0-239.255.255.255
    ");
            exit(errno);
        }
    
    /* 绑定自己的端口和IP信息到socket上 */
    if (bind
            (sockfd, (struct sockaddr *) &peeraddr,
             sizeof(struct sockaddr_in)) == -1) {
        printf("Bind error
    ");
        exit(0);
    }
    
    /* 循环接收网络上来的组播消息 */
    for (;;) {
        bzero(recmsg, BUFLEN + 1);
        n = recvfrom(sockfd, recmsg, BUFLEN, 0,
                (struct sockaddr *) &peeraddr, &socklen);
        if (n < 0) {
            printf("recvfrom err in udptalk!
    ");
            exit(4);
        } else {
            /* 成功接收到数据报 */
            recmsg[n] = 0;
            printf("peer:%s", recmsg);
        }
    }
    }
    

      Linux客户端

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define BUFLEN 255
    /*********************************************************************
     *filename: mcastclient.c
     *purpose: 演示组播编程的基本步骤,其实这就是一个基本的UDP客户端程序
     *tidied by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com)
     Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言
     *date time:2007-01-25 13:10:00
     *Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途
     * 但请遵循GPL
     *Thanks to: Google.com
     *Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力
     * 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!
     *********************************************************************/
    int main(int argc, char **argv)
    {
        struct sockaddr_in peeraddr, myaddr;
    
        int sockfd;
        char recmsg[BUFLEN + 1];
        unsigned int socklen;
    
        /* 创建 socket 用于UDP通讯 */
        sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (sockfd < 0) {
            printf("socket creating error
    ");
            exit(1);
        }
        socklen = sizeof(struct sockaddr_in);
    
        /* 设置对方的端口和IP信息 */
        memset(&peeraddr, 0, socklen);
        peeraddr.sin_family = AF_INET;
        if (argv[2])
            peeraddr.sin_port = htons(atoi(argv[2]));
        else
            peeraddr.sin_port = htons(7838);
        if (argv[1]) {
            /* 注意这里设置的对方地址是指组播地址,而不是对方的实际IP地址 */
            if (inet_pton(AF_INET, argv[1], &peeraddr.sin_addr) <= 0) {
                printf("wrong group address!
    ");
                exit(0);
            }
        } else {
            printf("no group address!
    ");
            exit(0);
        }
    
        /* 设置自己的端口和IP信息 */
        memset(&myaddr, 0, socklen);
        myaddr.sin_family = AF_INET;
        if (argv[4])
            myaddr.sin_port = htons(atoi(argv[4]));
        else
            myaddr.sin_port = htons(23456);
    
        if (argv[3]) {
            if (inet_pton(AF_INET, argv[3], &myaddr.sin_addr) <= 0) {
                printf("self ip address error!
    ");
                exit(0);
            }
        } else
            myaddr.sin_addr.s_addr = INADDR_ANY;
    
        /* 绑定自己的端口和IP信息到socket上 */
        if (bind
                (sockfd, (struct sockaddr *) &myaddr,
                 sizeof(struct sockaddr_in)) == -1) {
            printf("Bind error
    ");
            exit(0);
        }
    
        /* 循环接受用户输入的消息发送组播消息 */
        for (;;) {
            /* 接受用户输入 */
            bzero(recmsg, BUFLEN + 1);
            if (fgets(recmsg, BUFLEN, stdin) == (char *) EOF)
                exit(0);
            /* 发送消息 */
            if (sendto
                    (sockfd, recmsg, strlen(recmsg), 0,
                     (struct sockaddr *) &peeraddr,
                     sizeof(struct sockaddr_in)) < 0) {
                printf("sendto error!
    ");
                exit(3);
            }
            printf("'%s' send ok
    ", recmsg);
        }
    }
    

      windows收发可用,linux发可用,收每隔一段时间收到一堆包,不能实时接收,可能是防火墙之类的问题。

    JAVA 版客户端

    import java.net.DatagramPacket;
    import java.net.InetAddress;
    import java.net.MulticastSocket;
    public class SocketClient {
    
      public static void main(String[] args) 
      {
    	  int port=9111;
    	  String host="239.255.255.239"; 
         // String data ="{"REMOTEHMI":{"type":"requestConnection","IP":"10.173.189.37","port":57527,"deviceName":"SM-G9350","uuid":"c0a303c1-efb8-45cb-a159-cd0143e368a8","oem":"audi"}}";
    	  String data="Hello world";
    	  while(true)
    	  {
          try 
          {
              InetAddress ip = InetAddress.getByName(host);
              DatagramPacket packet = new DatagramPacket(data.getBytes(),data.length(),ip,port);
              MulticastSocket ms = new MulticastSocket(55665);
              
              InetAddress LoaclIp = InetAddress.getByName("192.168.199.133");
              ms.setInterface(LoaclIp);
              
              ms.setLoopbackMode(false);
              ms.joinGroup(ip);  
              ms.setTimeToLive(1);  
              ms.send(packet);
              System.out.println("I have send it");
              ms.close();
          } 
          catch (Exception e) 
          {
              e.printStackTrace();
          }
    	  }
      }
    }
    

      

    InetAddress LoaclIp = InetAddress.getByName("192.168.199.133");
    ms.setInterface(LoaclIp);
    

      这两行一定要加上,我在真机测试时,发现无线网卡没有多播包,调查好久才知道,VC和java对默认网卡选择上不一样

    vc默认ipconfig的第一个网卡,JAVA默认控制面板网络连接第一个,正好是一个虚拟网卡,所以没有抓到包。

  • 相关阅读:
    深入了解css的行高Line Height属性
    Kafka消息队列
    架构图
    清理肠道好方法
    维特根斯坦
    ES查询DSL大于小于写法
    python虚拟环境
    Dockerfile
    flask基本使用
    泛型类多个类型参数的定义
  • 原文地址:https://www.cnblogs.com/Browneyes/p/6917687.html
Copyright © 2011-2022 走看看