zoukankan      html  css  js  c++  java
  • linux学习之多高并发服务器篇(三)

    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 ...
    "); 
    
      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
  • 相关阅读:
    现代软件工程 第一章 概论 第4题——邓琨
    现代软件工程 第一章 概论 第9题——邓琨
    现代软件工程 第一章 概论 第7题——张星星
    现代软件工程 第一章 概论 第5题——韩婧
    hdu 5821 Ball 贪心(多校)
    hdu 1074 Doing Homework 状压dp
    hdu 1074 Doing Homework 状压dp
    hdu 1069 Monkey and Banana LIS变形
    最长上升子序列的初步学习
    hdu 1024 Max Sum Plus Plus(m段最大子列和)
  • 原文地址:https://www.cnblogs.com/zzdbullet/p/9513685.html
Copyright © 2011-2022 走看看