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;
}

 

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