1. 程式人生 > >linux學習之多高並發服務器篇(三)

linux學習之多高並發服務器篇(三)

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學習之多高並發服務器篇(三)