linux學習之多高並發服務器篇(三)
阿新 • • 發佈:2018-08-21
strong recvfrom printf .com getaddr from ica 1.0 有一個
UDP多播服務器
多播
組播組可以是永久的也可以是臨時的。組播組地址中,有一部分由官方分配的,稱為永久組播組。永久組播組保持不變的是它的ip地址,組中的成員構成可以發 生變化。永久組播組中成員的數量都可以是任意的,甚至可以為零。那些沒有保留下來供永久組播組使用的ip組播地址,可以被臨時組播組利用。
224.0.0.0~224.0.0.255為預留的組播地址(永久組地址),地址224.0.0.0保留不做分配,其它地址供路由協議使用;
224.0.1.0~224.0.1.255是公用組播地址,可以用於Internet; 224.0.2.0~238.255.255.255為用戶可用的組播地址(臨時組地址),全網範圍內有效;
239.0.0.0~239.255.255.255為本地管理組播地址,僅在特定的本地範圍內有效。
ip ad
查看網卡編號
if_nametoindex
將幾臺電腦分為一個組,同一個組內本身每個電腦都有自己的ip地址,同組的都有一個組號,若想把一個包發給一個組,目的ip設為組號。一對多的數據傳輸,在ip層存在一個組播的概念,客戶端的ip地址沒有意義了,客戶端要接受的端口號仍然有意義,tcp或udp封裝端口號,說明哪個進程接受,一般應用於UDP領域,TCP用的非常少。
若server要發一個組播包,write(sockfd,buf,buflen);引入一個新的函數setsockopt,可以設置多層協議。
實例:
/* server.c */
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include<net/if.h>
#include "wrap.h"
#define MAXLINE 80
#define SERV_PORT 8000
#define CLIENT_PORT 9000//客戶端的端口號
#define GROUP "239.0.0.2"
int main(void)
{
struct sockaddr_in servaddr, cliaddr;//用於IPv4的地址
socklen_t cliaddr_len;
int sockfd;//文件描述符
char buf[MAXLINE];
char str[INET_ADDRSTRLEN];//16 Bytes
struct ip_mreqn group;
ssize_t len;
int i, n;
/*構造用於UDP通信的套接字*/
sockfd = socket(AF_INET, SOCK_DGRAM, 0);//
bzero(&servaddr, sizeof(servaddr));//將地址清零
//設置地址
servaddr.sin_family = AF_INET;/*IPv4*/
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//網絡字節數,本地任意IP
servaddr.sin_port = htons(SERV_PORT);
bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
/*設置組地址*/
inet_pton(AF_INET,GROUP,&group.imr_multiaddr);
/*本地任意IP*/
inet_pton(AF_INET,"0.0.0.0",&group.imr_address);
/*eth0-->編號 命令:ip ad*/
group.imr_ifindex=if_nametoindex("eth0");
setsockopt(sockfd,IPPROTO_IP,IP_MULTICAST_IF,&group,sizeof(group));
/*構造client 地址 IP+端口*/
bzero(&clientaddr, sizeof(clientaddr));//將地址清零 //設置地址
clientaddr.sin_family = AF_INET;/*IPv4*/
inet_pton(AF_INET,GROUP,&clientaddr.sin_addr.s_addr);
clientaddr.sin_port=htons(CLIENT_PORT);
printf("Accepting connections ...\n");
while (1)
{
fgets(buf,sizeof(buf),stdin);
sendto(sockfd,buf,strlen(buf),0,(struct sockaddr *)&clientaddr,sizeof(clinetaddr));
}
close(sockfd);
return 0;
}
/* client.c */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include<net/if.h>
#include <netinet/in.h>
#include "wrap.h"
#define MAXLINE 4096
#define SERVER_PORT 8000
#define CLIENT_PORT 9000
#define GROUP "239.0.0.2”
int main(int argc, char *argv[])
{
struct sockaddr_in serveraddr,localaddr;
int confd;
ssize_t len;
struck ip_mreqn group;//組播結構體
char buf[MAXLINE];
//1.創建一個socket
confd=socket(AF_INET,SOCK_DGRAM,0);
//2.初始化本地端地址
bzero(&localaddr,sizeof(localaddr));
localaddr.sin_family=AF_INET;
inet_pton(AF_INET,"0.0.0.0",&localaddr.sin_addr.s_addr);
localaddr.sin_port=htons(CLIENT_PORT);
bind(confd,(struct sockaddr *)&localaddr,sizeof(localaddr));
//加入多播組
inet_pton(AF_INET,GROUP,&group.imr_multiaddr);
inet_pton(AF_INET,"0.0.0.0",&group.imr_address);
group.imr_ifindex=if_nametoindex("eth0");
//設置client加入多播組
setsockopt(confd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&group,sizeof(group));
while(1)
{
len=recvfrom(confd,buf,sizeof(buf),0,NULL,0);
write(STDOUT_FILENO,buf,len);
}
close(confd);
return 0;
}
其他常用函數
名字與地址轉換:
過時,僅用於IPv4,線程不安全
gethostbyname 通過網址知道ip地址
gethostbyaddr 通過IP地址知道網址
getservbyname
getservbyport
根據服務器程序名字或端口號獲取信息,用的不多
getaddrinfo
getnameinfo
freeaddrinfo
趨勢,可同時處理IPv4和IPv6,線程安全
套接口和地址關聯
getsockname
根據accept返回的的sockfd,得到臨時端口號
getpeername
根據accept返回的sockfd,得到遠端鏈接的端口號,在exec後可以獲取客戶端信息
來源https://www.cnblogs.com/rainbow1122/p/7891490.html
linux學習之多高並發服務器篇(三)