無論是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;
}