UDP单播 组播 广播 区别及简单实现

无论是tcp还是udp 服务器都必须绑定prot、Ip,客户端可以有选择性。

udp单播: 单播只能是发送方往接收方指定的IP 端口发送数据

组播需具备的条件  1、接收方设置组播属性及组播号  2、发送方往接收方定义的组播地址发送  3、服务器客户端端口号需要一致

广播需具备的条件 1、接收方设置广播属性  2、发送方往接收方定义的组播地址发送  3、服务器客户端端口号需要一致


组播和单播的区别:组播可以多设置一个IP(这里称为为组播地址224打头的),发送方除了可以往接收方绑定的IP发送,也可以                                                                                                                                                             往接收方设置的组播ip发送数据。
组播和广播的区别:广播需要设置启动接收广播属性,发送方除了可以往接收方绑定的IP发送,也可以往255同网段IP发送。

这三种udp模型  客户端的实现没有区别,区别仅仅在于发送的网络IP不一样

/------------------------------------------------------------------------------------------------------------------------------------------------------------------------

  udp unicast server code

/------------------------------------------------------------------------------------------------------------------------------------------------------------------------

/*udp和tcp客户端其实都可以绑定自身的IP端口也可以不绑定,
不绑定的话系统会为你默认分配,而服务器则必须绑定端口 IP*/

#include <Winsock2.h>
#include <iostream>
#include <thread>

#pragma comment(lib, "Ws2_32.lib")

using namespace std;

int main(void)
{
    /* 初始化winsock2库 */
    //Step 0. Initialize winsock2 library...
    WSADATA wsaData;

    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    {
        return 1;
    }

    // Step 1. Ask system for a socket.this socket is waiter
    SOCKET sockServer = ::socket(PF_INET, SOCK_DGRAM, 0);

    if (sockServer == INVALID_SOCKET)
    {
        return 1;
    }

    //Step 2. bind the socket to a local address and port.接待套接字
    sockaddr_in addrServer = { 0 };
    addrServer.sin_family = AF_INET;
    addrServer.sin_addr.S_un.S_addr = inet_addr("88.88.106.134");
    addrServer.sin_port = 30001;
    if (::bind(sockServer, reinterpret_cast<const sockaddr*>(&addrServer),
        sizeof addrServer) == SOCKET_ERROR)
    {
        return 1;
    }

    char buf[100] = { 0 };
    sockaddr_in addrClient;
    int iSize = sizeof(addrClient);

   //recvfrom是阻塞的

    int iResult = recvfrom(sockServer, buf, 100, 0, reinterpret_cast<sockaddr*>(&addrClient), &iSize);

    closesocket(sockServer);
    WSACleanup();
    return 0;
}

 

/------------------------------------------------------------------------------------------------------------------------------------------------------------------------

  udp unicast Client code

/------------------------------------------------------------------------------------------------------------------------------------------------------------------------

#include <Winsock2.h>
#include <iostream>
#include <thread>

#pragma comment(lib, "Ws2_32.lib")

using namespace std;

int main(void)
{
    /* 初始化winsock2库 */
    //Step 0. Initialize winsock2 library...
    WSADATA wsaData;

    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    {
        return 1;
    }

    // Step 1. Ask system for a socket.this socket is waiter
    SOCKET sock2Server = ::socket(PF_INET, SOCK_DGRAM, 0);

    if (sock2Server == INVALID_SOCKET)
    {
        return 1;
    }

    //绑定自己的port  客户端也可以绑定自己的port ip 指定数据从什么端口出去
    //sockaddr_in addrBind = { 0 };
    //addrBind.sin_family = AF_INET;
    //addrBind.sin_addr.S_un.S_addr = inet_addr("88.88.106.134");
    //addrBind.sin_port = 30002;
    //if (::bind(sock2Server, reinterpret_cast<const sockaddr*>(&addrBind),
    //    sizeof addrBind) == SOCKET_ERROR)
    //{
    //    return 1;
    //}

    //设置接收方的port ip 下面的端口 ip需要和服务器一致
    sockaddr_in addrServer = { 0 };
    addrServer.sin_family = AF_INET;
    addrServer.sin_addr.S_un.S_addr = inet_addr("88.88.106.134");
    addrServer.sin_port = 30001;

    sendto(sock2Server, "hello", 6, 0, reinterpret_cast<sockaddr*>(&addrServer), sizeof(addrServer));

    closesocket(sock2Server);
    WSACleanup();
    return 0;
}

 

 

/------------------------------------------------------------------------------------------------------------------------------------------------------------------------

  udp muticast server code

/------------------------------------------------------------------------------------------------------------------------------------------------------------------------

#include <Winsock2.h>
#include <iostream>
#include <thread>
#include<Ws2tcpip.h>   //需要加上此头文件
#pragma comment(lib, "Ws2_32.lib")

using namespace std;

int main(void)
{
    /* 初始化winsock2库 */
    //Step 0. Initialize winsock2 library...
    WSADATA wsaData;

    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    {
        return 1;
    }

    // Step 1. Ask system for a socket.this socket is waiter
    SOCKET sockServer = ::socket(PF_INET, SOCK_DGRAM, 0);

    if (sockServer == INVALID_SOCKET)
    {
        return 1;
    }

    //Step 2. bind the socket to a local address and port.接待套接字
    sockaddr_in addrServer = { 0 };
    addrServer.sin_family = AF_INET;
    addrServer.sin_addr.S_un.S_addr = inet_addr("88.88.106.134");
    addrServer.sin_port = 30001;
    if (::bind(sockServer, reinterpret_cast<const sockaddr*>(&addrServer),
        sizeof addrServer) == SOCKET_ERROR)
    {
        return 1;
    }

    //设置接收组播属性 

    ip_mreq mrq;
    mrq.imr_multiaddr.S_un.S_addr = inet_addr("224.0.0.11");//设置组播地址 满足前面是224即可224.0.0.1不能用
    mrq.imr_interface.S_un.S_addr = 0;   //设置自动选择网卡上面接收组播

    if (setsockopt(sockServer, IPPROTO_IP, IP_ADD_MEMBERSHIP, reinterpret_cast<const char*>(&mrq), sizeof(mrq))                 ==    SOCKET_ERROR)
    {
        return 1;
    }


    char buf[100] = { 0 };
    sockaddr_in addrClient;
    int iSize = sizeof(addrClient);

    int iResult = recvfrom(sockServer, buf, 100, 0, reinterpret_cast<sockaddr*>(&addrClient), &iSize);

    closesocket(sockServer);
    WSACleanup();
    return 0;
}

/------------------------------------------------------------------------------------------------------------------------------------------------------------------------

  udp muticast client code

/------------------------------------------------------------------------------------------------------------------------------------------------------------------------

#include <Winsock2.h>
#include <iostream>
#include <thread>

#pragma comment(lib, "Ws2_32.lib")

using namespace std;

int main(void)
{
    /* 初始化winsock2库 */
    //Step 0. Initialize winsock2 library...
    WSADATA wsaData;

    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    {
        return 1;
    }


    SOCKET sock2Server = ::socket(PF_INET, SOCK_DGRAM, 0);

    if (sock2Server == INVALID_SOCKET)
    {
        return 1;
    }

 
    //设置接收方的port ip 下面的端口
    sockaddr_in addrServer = { 0 };
    addrServer.sin_family = AF_INET;
    //点对点的也可以
    //addrServer.sin_addr.S_un.S_addr = inet_addr("88.88.106.134");
    //往服务器组播地址发也可以,相比单播多一个选择性 
    addrServer.sin_addr.S_un.S_addr = inet_addr("224.0.0.11");
    addrServer.sin_port = 30001;

    sendto(sock2Server, "hello", 6, 0, reinterpret_cast<sockaddr*>(&addrServer), sizeof(addrServer));

    closesocket(sock2Server);
    WSACleanup();
    return 0;
}

 

/------------------------------------------------------------------------------------------------------------------------------------------------------------------------

  udp broadcast server code

/------------------------------------------------------------------------------------------------------------------------------------------------------------------------


//具备广播的条件  1、接收方设置广播属性 2、发送方往同网段的255IP地址发送 3、服务器客户端端口号需要一致
#include <Winsock2.h>
#include <iostream>
#include <thread>

#pragma comment(lib, "Ws2_32.lib")

using namespace std;

int main(void)
{
    /* 初始化winsock2库 */
    //Step 0. Initialize winsock2 library...
    WSADATA wsaData;

    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    {
        return 1;
    }

    // Step 1. Ask system for a socket.this socket is waiter
    SOCKET sockServer = ::socket(PF_INET, SOCK_DGRAM, 0);

    if (sockServer == INVALID_SOCKET)
    {
        return 1;
    }

    //Step 2. bind the socket to a local address and port.接待套接字
    sockaddr_in addrServer = { 0 };
    addrServer.sin_family = AF_INET;
    addrServer.sin_addr.S_un.S_addr = inet_addr("88.88.106.134");
    addrServer.sin_port = 30001;
    if (::bind(sockServer, reinterpret_cast<const sockaddr*>(&addrServer),
        sizeof addrServer) == SOCKET_ERROR)
    {
        return 1;
    }

    //设置接收广播属性 要设置了广播属性才可以接收广播消息   
    bool bEnableBroadcast = true;
    if (setsockopt(sockServer, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<const char*>(&bEnableBroadcast),                                               sizeof(bEnableBroadcast)) == SOCKET_ERROR)
    {
        return 1;
    }

    

    char buf[100] = { 0 };
    sockaddr_in addrClient;
    int iSize = sizeof(addrClient);

    int iResult = recvfrom(sockServer, buf, 100, 0, reinterpret_cast<sockaddr*>(&addrClient), &iSize);

    closesocket(sockServer);
    WSACleanup();
    return 0;
}

/------------------------------------------------------------------------------------------------------------------------------------------------------------------------

  udp broadcast client code

/------------------------------------------------------------------------------------------------------------------------------------------------------------------------

#include <Winsock2.h>
#include <iostream>
#include <thread>

#pragma comment(lib, "Ws2_32.lib")

using namespace std;

int main(void)
{
    /* 初始化winsock2库 */
    //Step 0. Initialize winsock2 library...
    WSADATA wsaData;

    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    {
        return 1;
    }

    // Step 1. Ask system for a socket.this socket is waiter
    SOCKET sock2Server = ::socket(PF_INET, SOCK_DGRAM, 0);

    if (sock2Server == INVALID_SOCKET)
    {
        return 1;
    }

    //广播中服务器设置了广播属性的话 下
    //设置接收方的port ip 下面的端口
    sockaddr_in addrServer = { 0 };
    addrServer.sin_family = AF_INET;
    //点对点的也可以
    //addrServer.sin_addr.S_un.S_addr = inet_addr("88.88.106.134");
    //往255这个网段发的话 只要是设置了广播属性的服务器都可以接收到数据 
    addrServer.sin_addr.S_un.S_addr = inet_addr("88.88.106.255");
    addrServer.sin_port = 30001;

    sendto(sock2Server, "hello", 6, 0, reinterpret_cast<sockaddr*>(&addrServer), sizeof(addrServer));

    closesocket(sock2Server);
    WSACleanup();
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章