• 【linux高级程序设计】(第十四章)TCP高级应用 3


    控制socket文件描述符属性

    1.set/getsockopt()修改socket属性

    int getsockopt (int __fd, int __level, int __optname, void *__restrict __optval, socklen_t *__restrict __optlen):获得某个套接字的属性。成功0,失败-1

    int setsockopt (int __fd, int __level, int __optname, __const void *__optval, socklen_t __optlen) :设置某个套接字属性

    参数1:套接字描述符。

    参数2:指定套接字属性的分类,标识某个协议级别

    #define SOL_SOCKET   1    //通用套接字选项
    #define IPPROTO_IP   0    //IP选项
    #define IPPROTO_TCP  6    //TCP选项

    参数3:指定控制的参数,在参数2不同的情况下有不同选项

    SOL_SOCKET的选项如下:

    IPPROTO_IP选项如下:

    IPPROTO_TCP选项如下:

    参数4:套接字选项值,根据选项名称的数据类型进行转换

    参数5:缓冲区大小,返回时为反向的值的长度。

    例子:列出某个socket对象的基本信息

    #include<stdio.h>
    #include<stdlib.h>
    #include<errno.h>
    #include<string.h>
    #include<sys/types.h>
    #include<netinet/in.h>
    #include<netinet/tcp.h>
    #include<sys/socket.h>
    #include<sys/wait.h>
    #include<unistd.h>
    #include<arpa/inet.h>
    #include<sys/time.h>
    int main(int argc, char *argv[])
    {
        int rcvbuf_size;
        int sndbuf_size;
        int type = 0;
        socklen_t size;
        int sock_fd;
        struct timeval set_time, ret_time;
        if((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
        {
            perror("socket");
            exit(EXIT_FAILURE);
        }
        //获取发送缓冲区大小
        size = sizeof(sndbuf_size);
        getsockopt(sock_fd, SOL_SOCKET, SO_SNDBUF, &sndbuf_size, &size);
        printf("sndbuf_size = %d
    ", sndbuf_size);
        //获取接收缓冲区大小
        size = sizeof(rcvbuf_size);
        getsockopt(sock_fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf_size, &size);
        printf("rcvbuf_size = %d
    ", rcvbuf_size);
        //获取socket类型
        size = sizeof(type);
        getsockopt(sock_fd, SOL_SOCKET, SO_TYPE, &type, &size);
        printf("type = %d
    ", type);
        //获取发送超时值
        size = sizeof(struct timeval);
        getsockopt(sock_fd, SOL_SOCKET, SO_SNDTIMEO, &ret_time, &size);
        printf("default: time out is %ds and %dus
    ", ret_time.tv_sec, ret_time.tv_usec);
        //修改超时值
        set_time.tv_sec = 10;
        set_time.tv_usec = 100;
        setsockopt(sock_fd, SOL_SOCKET, SO_SNDTIMEO, &set_time, size);
        getsockopt(sock_fd, SOL_SOCKET, SO_SNDTIMEO, &ret_time, &size);
        printf("after modify: time out is %ds and %dus
    ", ret_time.tv_sec, ret_time.tv_usec);
        //读取TTL值
        int ttl = 0;
        size = sizeof(ttl);
        getsockopt(sock_fd, IPPROTO_IP, IP_TTL, &ttl, &size);
        printf("the default ip ttl is %d
    ", ttl);
        //读取TCP_MAXSEG值
        int maxseg = 0;
        size = sizeof(maxseg);
        getsockopt(sock_fd, IPPROTO_TCP, TCP_MAXSEG, &maxseg, &size);
        printf("the TCP max seg is %d
    ", maxseg);
    }

    效果

    2.fcntl控制socket

    1.控制socket为非阻塞方式

    int flags;
    if((flags = fcntl(fd, F_GETFL, 0)) < 0)
    {
        perror("fcntl");
        exit(EXIT_FAILURE);
    }
    flags |= O_NONBLOCK;
    if(fcntl(fd, F_SETFL, flags) < 0)
    {
        perror("fcntl");
        exit(EXIT_FAILURE);
    }

    2.设置socket为信号驱动型。socket状态改变时产生SIGIO信号

    int flags;
    if((flags = fcntl(fd, F_GETFL, 0)) < 0)
    {
        perror("fcntl");
        exit(EXIT_FAILURE);
    }
    flags |= O_ASYNC;
    if(fcntl(fd, F_SETFL, flags) < 0)
    {
        perror("fcntl");
        exit(EXIT_FAILURE);
    }

    3.使用F_SETOWN选项设置socket的拥有者以及接收SIGIO和SIGURG信号。

    fcntl(socket, F_SETOWN, getpid());

    4.使用F_GETOWN选项获取某socket拥有者

    fcntl(socket, F_GETOWN, getpid());

    3.ioctl控制文件描述符

    可以对socket文件描述符执行特殊处理。需要#include<stropts.h>

    int ioctl (int fildes, int request, ... /*arg*/)

    常用选项:

    文件相关操作:

    Socket相关操作

    网络接口配置控制

    ARP cache操作

    RARP cache控制

    第三个参数有专门的数据结构struct ifreq提供具体的操作

    例子:获取本机端口eth0所对应的IP地址

    #include<net/if.h>
    #include<sys/ioctl.h>
    #include<string.h>
    #include<stdio.h>
    #include<sys/socket.h>
    #include<arpa/inet.h>
    int main()
    {
        int inet_sock;
        struct ifreq ifr;
        inet_sock = socket(AF_INET, SOCK_DGRAM, 0);
        strcpy(ifr.ifr_name, "eth0");
        if(ioctl(inet_sock, SIOCGIFADDR, &ifr) < 0)
            perror("ioctl");
        printf("%s
    ", inet_ntoa(((struct sockaddr_in*)&(ifr.ifr_addr))->sin_addr));
    }

    获取指定接口的MAC地址

    #include<net/if.h>
    #include<sys/ioctl.h>
    #include<string.h>
    #include<stdio.h>
    #include<sys/socket.h>
    #include<arpa/inet.h>
    #include<stdlib.h>
    
    int main(int argc, char * argv[])
    {
        int i;
        struct ifreq ifreq;
        int sock;
        char mac[32];
        if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
        {
            perror("error");
            exit(EXIT_FAILURE);
        }
        strcpy(ifreq.ifr_name, argv[1]);
        if(ioctl(sock, SIOCGIFHWADDR, &ifreq) < 0)
        {
            perror("error:");
            exit(EXIT_FAILURE);
        }
        //输出MAC信息
        for(i = 0; i < 6; i++)
        {
            sprintf(mac + 3 * i, "%02x:", (unsigned char)ifreq.ifr_hwaddr.sa_data[i]);
        }
        mac[17] = '';
        printf("mac addr is: %s
    ", mac);
        return 0;
    }

  • 相关阅读:
    GPU 加速NLP任务(Theano+CUDA)
    SOJ 1717 Computer (单机任务调度)
    CNN for NLP (CS224D)
    数据分析:中国高校更名历史 Python
    TextRank 自动文摘
    深度学习笔记(十一)网络 Inception, Xception, MobileNet, ShuffeNet, ResNeXt, SqueezeNet, EfficientNet, MixConv
    深度学习笔记(七)SSD 论文阅读笔记简化
    在Windows下编译扩展OpenCV 3.1.0 + opencv_contrib 及一些问题
    win10 + gtx1060 + cuda8.0 + caffe + vs2013 + Tensorflow + PyTorch
    深度学习笔记(二十五)DenseBox & FCOS & PolarMask
  • 原文地址:https://www.cnblogs.com/dplearning/p/4703028.html
Copyright © 2020-2023  润新知