系统相关
首页 > 系统相关> > linux高性能服务器编程---第五章Linux网络编程基础API (3)

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
*/

 

标签:struct,int,编程,sockfd,API,Linux,msg,address,name
来源: https://www.cnblogs.com/mjhjl/p/16229087.html