• linux高性能服务器编程第五章Linux网络编程基础API (3)


    通用读写函数
    #inclued <sys/socket.h>
    ssize_t recvmsg(int sockfd, struct msghdr* msg, int flags);
    ssize_t sendmsg(int sockfd, struct msghdr* msg, int flags);
    
    struct msghdr
    {
    /* socket address --- 指向socket地址结构变量, 对于TCP连接需要设置为NULL*/
        void* msg_name; 
    
    
        socklen_t msg_namelen;
        
        /* 分散的内存块 --- 对于 recvmsg来说数据被读取后将存放在这里的块内存中, 内存的位置和长度由
         * msg_iov指向的数组指定, 称为分散读(scatter read)  ---对于sendmsg而言, msg_iovlen块的分散内存中
         * 的数据将一并发送称为集中写(gather write);
        */
        struct iovec* msg_iov;
        int msg_iovlen; /* 分散内存块的数量*/
        void* msg_control; /* 指向辅助数据的起始位置*/
        socklen_t msg_controllen; /* 辅助数据的大小*/
        int msg_flags; /* 复制函数的flags参数, 并在调用过程中更新*/
    };
    
    struct iovec
    {
        void* iov_base /* 内存起始地址*/
        size_t iov_len /* 这块内存长度*/
    }

    其他Api

    #include <sys/socket.h>
    // 用于判断 sockfd是否处于带外标记, 即下一个被读取到的数据是否是带外数据, 
    // 是的话返回1, 不是返回0
    // 这样就可以选择带MSG_OOB标志的recv调用来接收带外数据. 
    int sockatmark(int sockfd);
    
    // getsockname 获取sockfd对应的本端socket地址, 存入address指定的内存中, 长度存入address_len中 成功返回0失败返回-1
    // getpeername 获取远端的信息, 同上
    int getsockname(int sockfd, struct sockaddr* address, socklen_t* address_len);
    int getpeername(int sockfd, struct sockaddr* address, socklen_t* address_len);
    
    /* 以下函数头文件均相同*/
    
    // sockfd 目标socket, level执行操作协议(IPv4, IPv6, TCP) option_name 参数指定了选项的名字. 后面值和长度
    // 成功时返回0 失败返回-1
    int getsockopt(int sockfd, int level, int option_name, void* option_value, 
                            socklen_t restrict option_len);
    int setsockopt(int sockfd, int level, int option_name, void* option_value, 
                            socklen_t restrict option_len);
    SO_REUSEADDR重用本地地址sock被设置此属性后, 即使sock在被bind()后处于TIME_WAIT状态, 此时与他绑定的socket地址依然能够立即重用来绑定新的sock
    SO_RCVBUF TCP接收缓冲区大小 最小值为256字节. 设置完后系统会自动加倍你所设定的值. 多出来的一倍将用用作空闲缓冲区处理拥塞
    SO_SNDBUF TCP发送缓冲区大小 最小值为2048字节
    SO_RCVLOWAT 接收的低水位标记 默认为1字节, 当TCP接收缓冲区中可读数据的总数大于其低水位标记时, IO复用系统调用将通知应用程序可以从对应的socket上读取数据
    SO_SNDLOWAT 发送的高水位标记 默认为1字节, 当TCP发送缓冲区中空闲空间大于低水位标记的时候可以写入数据
    SO_LINGER  
    struct linger
    {
        int l_onoff /* 开启非0, 关闭为0*/
        int l_linger; /* 滞留时间*/
        /*
        * 当onoff为0的时候此项不起作用, close调用默认行为关闭socket
        * 当onoff不为0 且linger为0, close将立即返回, TCP将丢弃发送缓冲区的残留数据, 同时发送一个复位报文段
        * 当onoff不为0 且linger大于0 . 当socket阻塞的时候close将会等待TCP模块发送完残留数据并得到确认后关 
        * 闭, 如果是处于非阻塞则立即关闭
        */
    };

     

    网络信息API

    #include <netdb.h>
    // 通过主机名查找ip
    struct hostent* gethostbyname(const char* name);
    
    // 通过ip获取主机完整信息 
    // type为IP地址类型 AF_INET和AF_INET6
    struct hostent* gethostbyaddr(const void* addr, size_t len, int type);
    
    struct hostent
    {
      char *h_name;            /* Official name of host.  */
      char **h_aliases;        /* Alias list.  */
      int h_addrtype;        /* Host address type.  */
      int h_length;            /* Length of address.  */
      char **h_addr_list;        /* List of addresses from name server.  */
    }
    
    int main(int argc, char* argv[])
    {
        if (argc != 2)
        {
            printf("非法输入\n");
            exit(0);
        }
        char* name = argv[1];
    
        struct hostent *hostptr{};
    
        hostptr = gethostbyname(name);
        if (hostptr == nullptr)
        {
            printf("输入存在错误 或无法获取\n");
            exit(0);
        }
    
        printf("Official name of hostptr: %s\n", hostptr->h_name);
    
        char **pptr;
        char inet_addr[INET_ADDRSTRLEN];
    
        printf("Alias list:\n");
        for (pptr = hostptr->h_aliases; *pptr != nullptr; ++pptr)
        {
            printf("\t%s\n", *pptr);
        }
    
        switch (hostptr->h_addrtype)
        {
            case AF_INET:
            {
                printf("List of addresses from name server:\n");
                for (pptr = hostptr->h_addr_list; *pptr != nullptr; ++pptr)
                {
                    printf("\t%s\n",
                            inet_ntop(hostptr->h_addrtype, *pptr, inet_addr, sizeof(inet_addr)));
                }
                break;
            }
            default:
            {
                printf("unknow address type\n");
                exit(0);
            }
        }
        return 0;
    }
    
    /*
    ./run baidu.com
    Official name of hostptr: baidu.com
    Alias list:
    List of addresses from name server:
        39.156.69.79
        220.181.38.148
    */
  • 相关阅读:
    hdu2049.java
    java输入输出流小细节
    滚动字幕
    hdu4504java
    HDU2054JAVA
    hdu2058java
    hdu2073递推题
    [转]SELinux管理与配置
    Can't connect to MySQL server on 'XXX' (13)
    CentOS6.5+php5.3听云安装过程
  • 原文地址:https://www.cnblogs.com/mjhjl/p/16229087.html
Copyright © 2020-2023  润新知