UDP通信
1. UDP

代碼實作流程如下所示
UDP通信程序
//服務器端
1. socket() 創建套接字
2. bind() 系結套接字
與TCP區別開來,沒有listen()、accept()建立連接的程序
3. 通信 recvfrom() sendto()
4. close
//客戶端
1. socket() 創建套接字
與TCP區別開來,沒有connect()建立連接的程序
2. 通信 sendto() recvfrom()
3. close()
//UDP 服務器端 - udpServer.cpp
int main(){
int fd = socket(PF_INET, SOCK_DGRAM, 0);
//注意SOCK_DGRAM TCP對應的第二個引數是SOCK_STREAM
if(fd == -1){
perror("udpServer.cpp socket() errors");
exit(-1);
}
struct sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = INADDR_ANY;
serverAddr.sin_port = htons(8888);
int ret = bind(fd, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
if(ret == -1){
perror("udpServer.cpp bind() errors");
exit(-1);
}
while(1){
char buf[BUFSIZ];
char ipBuf[16];
struct sockaddr_in clientAddr;
socklen_t size = sizeof(clientAddr);
int len = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *) &clientAddr, &size);
cout << "client IP = " << inet_ntop(AF_INET, &clientAddr.sin_addr.s_addr, ipBuf, sizeof(ipBuf))
<< "client PORT = " << ntohs(clientAddr.sin_port) << endl;
cout << "server recv : " << buf << endl;
sendto(fd, buf, strlen(buf) + 1, 0, (struct sockaddr *) &clientAddr, sizeof(clientAddr));
}
close(fd);
return 0;
}
//UDP 客戶端 - udpClient.cpp
int main() {
int fd = socket(PF_INET, SOCK_DGRAM, 0);
if(fd == -1) {
perror("socket");
exit(-1);
}
struct sockaddr_in clientAddr;
clientAddr.sin_family = AF_INET;
clientAddr.sin_port = htons(8888);
inet_pton(AF_INET, "127.0.0.1", &clientAddr.sin_addr.s_addr);
int num = 0;
while(1) {
char buf[BUFSIZ];
sprintf(buf, "hello , i am client %d \n", num++);
sendto(fd, buf, strlen(buf) + 1, 0, (struct sockaddr *)&clientAddr, sizeof(clientAddr));
int len = recvfrom(fd, buf, sizeof(buf), 0, NULL, NULL);
cout << "client recv : " << buf << endl;
sleep(1);
}
close(fd);
return 0;
}
2. 廣播與組播
先講講 廣播 與后面要實作的 組播(多播) 的區別
廣播:向子網中的多臺計算機發送訊息,
1.特征:
IP地址由網路號+主機號構成,而廣播則是主機標識部分全為1,即必須滿足 *.*.*.255結尾
2.應用:
A.只能在局域網中使用;
B.客戶端需要系結服務使用的埠,才能收到廣播訊息,
3.實作:
設定廣播屬性的函式setsockport()
組播(多播):
1.聯系:
A.單播地址標識單個IP介面;
B.廣播地址表示某個子網的所有IP介面;
C.多播地址標識一組IP介面,是前兩種的折中方案,
2.應用:
A.既可以用于局域網,又可以用于跨廣域網;
B.客戶端需要加入多播組,才能接受到多播的資料,
廣播圖

組播圖(多播):

廣播代碼實作流程如下所示
廣播通信
//服務器端
1. socket() 創建套接字
2. setsockpot()設定廣播屬性
3. 創建一個廣播的地址 inet_pton
4. 通信 recvfrom() sendto()
5. close
//客戶端
1. socket() 創建套接字
2. 客戶端系結本地的IP和PORT
3. 通信 sendto() recvfrom()
4. close()
廣播代碼實作如下所示
//廣播 服務器端
int main() {
int fd = socket(PF_INET, SOCK_DGRAM, 0);
if(fd == -1) {
perror("socket");
exit(-1);
}
int op = 1;
setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &op, sizeof(op));
struct sockaddr_in cliaddr;
cliaddr.sin_family = AF_INET;
cliaddr.sin_port = htons(9999);
inet_pton(AF_INET, "172.25.191.255", &cliaddr.sin_addr.s_addr);
int num = 0;
while(1) {
char sendBuf[128];
sprintf(sendBuf, "hello, client....%d\n", num++);
// 發送資料
sendto(fd, sendBuf, strlen(sendBuf) + 1, 0, (struct sockaddr *)&cliaddr, sizeof(cliaddr));
printf("廣播的資料:%s\n", sendBuf);
sleep(1);
}
close(fd);
return 0;
}
//廣播 客戶端端
int main() {
int fd = socket(PF_INET, SOCK_DGRAM, 0);
if(fd == -1) {
perror("socket");
exit(-1);
}
struct in_addr in;
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(9999);
addr.sin_addr.s_addr = INADDR_ANY;
int ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
if(ret == -1) {
perror("bind");
exit(-1);
}
while(1) {
char buf[128];
int num = recvfrom(fd, buf, sizeof(buf), 0, NULL, NULL);
printf("server say : %s\n", buf);
}
close(fd);
return 0;
}
組播實作流程如下所示:
多播通信
//服務器端
1. socket() 創建套接字
2. setsockpot()設定多播屬性
3. 初始化客戶端的地址資訊 IP PORT
4. 通信 recvfrom() sendto()
5. close
//客戶端
1. socket() 創建套接字
2. 客戶端bind系結本地的IP和PORT
3. setsockopt加入多播組
4. 通信 sendto() recvfrom()
5. close()
//多播服務器端
int main() {
// 1.創建一個通信的socket
int fd = socket(PF_INET, SOCK_DGRAM, 0);
if(fd == -1) {
perror("socket");
exit(-1);
}
// 2.設定多播的屬性,設定外出介面
struct in_addr imr_multiaddr;
// 初始化多播地址
inet_pton(AF_INET, "239.0.0.10", &imr_multiaddr.s_addr);
setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &imr_multiaddr, sizeof(imr_multiaddr));
// 3.初始化客戶端的地址資訊
struct sockaddr_in cliaddr;
cliaddr.sin_family = AF_INET;
cliaddr.sin_port = htons(9999);
inet_pton(AF_INET, "239.0.0.10", &cliaddr.sin_addr.s_addr);
// 3.通信
int num = 0;
while(1) {
char sendBuf[128];
sprintf(sendBuf, "hello, client....%d\n", num++);
// 發送資料
sendto(fd, sendBuf, strlen(sendBuf) + 1, 0, (struct sockaddr *)&cliaddr, sizeof(cliaddr));
printf("組播的資料:%s\n", sendBuf);
sleep(1);
}
close(fd);
return 0;
}
//多播客戶端
int main() {
// 1.創建一個通信的socket
int fd = socket(PF_INET, SOCK_DGRAM, 0);
if(fd == -1) {
perror("socket");
exit(-1);
}
struct in_addr in;
// 2.客戶端系結本地的IP和埠
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(9999);
addr.sin_addr.s_addr = INADDR_ANY;
int ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
if(ret == -1) {
perror("bind");
exit(-1);
}
struct ip_mreq op;
inet_pton(AF_INET, "239.0.0.10", &op.imr_multiaddr.s_addr);
op.imr_interface.s_addr = INADDR_ANY;
// 加入到多播組
setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &op, sizeof(op));
// 3.通信
while(1) {
char buf[128];
// 接收資料
int num = recvfrom(fd, buf, sizeof(buf), 0, NULL, NULL);
printf("server say : %s\n", buf);
}
close(fd);
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/354584.html
標籤:其他
上一篇:docker-compsose 搭建minio集群(2021-10月-11月左右的版本)+nginx反向代理及負載均衡(配置超詳細講解)
