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

    UDP多播服务器

    多播

      组播组可以是永久的也可以是临时的。组播组地址中,有一部分由官方分配的,称为永久组播组。永久组播组保持不变的是它的ip地址,组中的成员构成可以发 生变化。永久组播组中成员的数量都可以是任意的,甚至可以为零。那些没有保留下来供永久组播组使用的ip组播地址,可以被临时组播组利用。 

    224.0.0.0224.0.0.255为预留的组播地址(永久组地址),地址224.0.0.0保留不做分配,其它地址供路由协议使用;  
    224.0.1.0224.0.1.255是公用组播地址,可以用于Internet; 
    224.0.2.0238.255.255.255为用户可用的组播地址(临时组地址),全网范围内有效;    239.0.0.0239.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后可以获取客户端信息
  • 相关阅读:
    centOS 6.5下升级mysql,从5.1升级到5.6
    利用PHP脚本辅助MySQL数据库管理5-检查异常数据
    利用PHP脚本辅助MySQL数据库管理4-两个库表结构差异比较
    利用PHP脚本辅助MySQL数据库管理3-删除重复表索引
    利用PHP脚本辅助MySQL数据库管理2-表主键表索引
    利用PHP脚本辅助MySQL数据库管理1-表结构
    Linux驱动设计——内存与IO访问
    Linux驱动设计—— 驱动调试技术
    Linux系统编程@终端IO
    Linux驱动设计—— 内外存访问
  • 原文地址:https://www.cnblogs.com/rainbow1122/p/7891490.html
Copyright © 2011-2022 走看看