haha组播windows2

#define  _WINSOCK_DEPRECATED_NO_WARNINGS 
#include <iostream>
#include<string>
#include <Winsock2.h>
#include <ws2tcpip.h> 
#include<vector>
using namespace std;
void ErrorCheck(int lcond, int rcond, string msg) {
    if (lcond != rcond)cout << "unexpected " << lcond << " " << msg << " failed!" << endl; 
}

#pragma comment(lib, "Ws2_32.lib")
void init() {
    WSADATA wsaData;
    (void)WSAStartup(MAKEWORD(2, 2), &wsaData);
}
void init_sockaddr(void* addrin, int len,string family, string addr, short port) {
    memset(addrin, 0, len);
    if (family == "ipv4") {
        sockaddr_in* tmp = (sockaddr_in*)addrin;
        tmp->sin_family = AF_INET;
        tmp->sin_port = htons(port);
        inet_pton(AF_INET, addr.c_str(), &tmp->sin_addr);
    }
    else {
        sockaddr_in6* tmp = (sockaddr_in6*)addrin;
        tmp->sin6_family = AF_INET6;
        tmp->sin6_port = htons(port);
        inet_pton(AF_INET6, addr.c_str(), &tmp->sin6_addr);
    }
}

class multicast {
public:
    SOCKET sock;
    ADDRESS_FAMILY family;
    int iface;
    char buf[1024];
    union {
        sockaddr_in in4;
        sockaddr_in6 in6;
    }nicaddr, groupaddr,srcaddr,senderaddr;
    
    multicast(string family, string nic, string group, short srcprt, short dstprt, int iface) {
        init_sockaddr(&nicaddr, sizeof nicaddr, family, nic, srcprt);
        init_sockaddr(&groupaddr, sizeof groupaddr, family, group, dstprt);
        this->family = family=="ipv4" ? AF_INET : AF_INET6;
        this->iface = iface;
        sock = socket(this->family, SOCK_DGRAM, IPPROTO_UDP);
        int tmp = 1;
        ErrorCheck(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&tmp, sizeof(int)),0,"reuseaddr");
        ErrorCheck(bind(sock, (sockaddr*)&nicaddr, sizeof nicaddr),0,"bind"); 
    }

    void includeGroupSource(vector<string> srcs) {
        for (auto& i : srcs) {
            group_source_req req;
            req.gsr_interface = iface;
            memcpy(&req.gsr_group, &groupaddr, sizeof groupaddr);
            init_sockaddr(&srcaddr, sizeof srcaddr, this->family == AF_INET ? "ipv4" : "ipv6",i, 0);
            memcpy(&req.gsr_source, &srcaddr, sizeof srcaddr);
            ErrorCheck(setsockopt(sock, this->family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6, 
                MCAST_JOIN_SOURCE_GROUP,
                (const char*)&req, sizeof req), 0, "join src");
            cout << "\tjoin src " << i<<"  "<< "include "  << endl;
        }
    }
    void excludeGroupSource(vector<string> srcs) {
        for (auto& i : srcs) {
            group_source_req req;
            req.gsr_interface = iface;
            memcpy(&req.gsr_group, &groupaddr, sizeof groupaddr);
            init_sockaddr(&srcaddr, sizeof srcaddr, this->family == AF_INET ? "ipv4" : "ipv6", i, 0);
            memcpy(&req.gsr_source, &srcaddr, sizeof srcaddr);
            group_req greq;
            greq.gr_interface = iface;
            memcpy(&greq.gr_group, &groupaddr, sizeof groupaddr);
            cout << "join group "  << endl;
            static int flag= 0;
            if(!flag)
                ErrorCheck(setsockopt(sock, this->family==AF_INET?IPPROTO_IP:IPPROTO_IPV6, MCAST_JOIN_GROUP, 
                (const char*)&greq, sizeof greq),0,"join group");
            flag = 1;
            ErrorCheck(setsockopt(sock, this->family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6,
                MCAST_BLOCK_SOURCE,
                (const char*)&req, sizeof req), 0, "join src");
            cout << "\tjoin src " << i << "  " << "exclude " << endl;
        }
    }
    void recv() {
        memset(buf, 0, sizeof buf);
        memset(&senderaddr, 0, sizeof senderaddr);
        int sendlen = sizeof senderaddr;
        int length = recvfrom(sock, buf, sizeof buf, 0, (sockaddr*)&senderaddr, &sendlen);
        cout << WSAGetLastError() << endl;
        char addr[256];
        memset(addr, 0, sizeof addr);
        if (length > 0) {
            int port = 0;
            if (family == AF_INET) {
                inet_ntop(family, &senderaddr.in4.sin_addr, addr, sizeof addr);
                port = htons(senderaddr.in4.sin_port);
            }
            else {
                inet_ntop(family, &senderaddr.in6.sin6_addr, addr, sizeof addr);
                port = htons(senderaddr.in6.sin6_port);
            }
            printf("received from (%s %d) %d %s\n", addr, port, length, buf);
        }
    }

    ~multicast() {
        closesocket(sock);
    }
};


int main(int argc, char* argv[]) {
    init();
    //multicast a("ipv4", "192.168.0.208", "225.3.3.3",1234,1234 ,11);
    multicast b("ipv6", "fe80::d5f3:f3bf:119a:5c3f", "ff3e::10",1234,1234,11);
    //a.addGroupSource(MCAST_INCLUDE, { "192.168.1.1","192.168.1.56"});
    b.excludeGroupSource({ "2001::1","2001::2"});
    while(1)
        b.recv();
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值