• linux学习笔记之套接字


    一、基础知识。

    1:套接字基础。

      1,是通信端点的抽象。

      2,在UNIX类系统中被当作是一种文件描述符。

      3,套接字通信域。

    描述
    AF_INET IPV4因特网域
    AF_INET6 IPV6因特网域
    AF_UNIX UNIX域
    AF_UPSPEC 未指定

      4,套接字类型。

    类型 描述
    SOCK_DGRAM 固定长度的,无链接的,不可考的报文传递
    SOCK_RAW IP协议的数据报接口
    SOCK_SEQPACKET 固定长度的,有序的,可靠的,面向连接的报文传递。
    SOCK_STREAM 有序的,可靠的,双向的,面向连接的字节流。

      5,协议。

    协议 描述
    IPPROTO_IP IPv4网际协议
    IPPROTO_IPV6 IPv6网际协议
    IPPROTO_ICMP 因特网控制报文协议(internet control message protocol)
    IPPROTO_RAW 原始IP数据包协议
    IPPROTO_TCP 传输控制协议
    IPPROTO_UDP 用户数据报协议(user datagram protocol)

      6,创建一个原始套接字需要root权限。

    2:套接字寻址和传输。

      1,在网络中,进程标识由:计算机网络地址(找到计算机) + 计算机的端口号(找到特定进程) 组成。

      2,大端和小端。

        1)大端字节序:最大字节地址上 保存 最低有效字节。

        2)小端字节序:最大字节地址上 保存 最高有效字节。

        3)大部分系统使用小端字节序。但TCP/IP使用大端字节序。

      3,域名系统( Domain name system,DNS)

      4,网络信息服务( Network information service, NIS )

      5,服务是由地址的端口号部分标示。每个服务由一个唯一的端口号支持。

      6,章16的代码在阅读结束后,进行尝试性理解和自编写。

      7,当异步IO中因为某种原因导致读/写阻塞,在阻塞条件不存在后,可以发送SIGIO信号来重新启用IO。步骤为:

        1)建立套接字所有权。这样信号可以被传递到对应的进程。

        2)通知套接字当IO操作不会阻塞时发送信号。

      8,带外数据

        1)含义:紧急数据。它有相对普通数据更高的优先级。

        2)部分通信协议支持此功能。(可选功能)

        3)当有新的紧急数据到来,旧有数据会被覆盖。

    3:套接字选项。

      1,套接字机制提供了 两个套接字选项接口:设置选项接口,查询选项接口。

    4:UNIX域套接字。

      1,IPC的一种:可以在同一计算机系统上运行的两个进程之间传递打开文件描述符。

        1)用于同一台计算机的进程通信。

        2)效率比因特网套接字高。因为它仅复制数据,无协议,无校验等复杂操作。

      2,一些实例(未阅读)。

        1)P508,借助UNIX域套接字轮询XSI消息队列。

        2)P512,将地址绑定到UNIX域套接字。

        3)P518,传送文件描述符:在两个进程之间传送打开文件描述符的技术非常有用。

      3,sockaddr_un结构体。

        1)可以将一个地址绑定到UNIX域套接字上。系统会使用该路径创建一个S_IFSOCK类型的文件。此文件无法打开。当关闭套接字时,必须显式的删除文件。

    二、相关函数。

    1:套接字。

    1 创建一个套接字
      int socket( int domain, int type, int protocol );
      // 1 参数protocol:通常为0。表示使用默认协议。
    2 禁止一个套接字IO
      int shutdown( int sockfd, int how );
      // 1 参数how:SHUT_RD,SHUT_WR,SHUT_RDWR

    2:寻址。

    1 处理器字节序 和 网络字节序 的转换。
      uint32_t htonl( uint32_t hostint32 );
      uint16_t htons( uint16_t hostint16 );
      uint32_t ntohl( uint32_t netint32 );
      uint16_t ntohl( uint16_t netint16 );
      // 1 h 主机,n 网络,l 长整数,s 短整数。
    2 地址通用结构体。
      struct socketaddr
      {
        sa_family_t    sa_family;    // address family
        char           sa_data[];    // variable-length address
        ...
      }
    3 网络地址的 二进制地址 和 文本字符串 相互转换
      const char *inet_ntop( int domain, const void *restrict addr, char *restrict str, socklen_t size );  // 二进制地址 转换成 文本字符串
      int inet_pton( int domain, const char *restrict str, void *restrict addr );  // 文本字符串 转换成 二进制地址。
    4 查询主机信息。
      struct hostent* gethostent( void );
      void sethostent( int stayopen );
      void endhostent( void );
      struct hostent
      {
        char    *h_name;       // name of host
        char    **h_aliases;   // pointer to alternate host name array
        int     h_addrtype;    // address type
        int     h_length;      // length in bytes of address
        char    **h_addr_list; // pointer to array of network address
        ...
      }
    5 获取网络名字 和 网络编号。
      struct netent* getnetbyaddr( uint32_t net, int type );
      struct netent* getnetbyname( const char *name );
      struct netent* getnetent( void );
      void setnetent( int stayopen );
      void endnetent( void );
      struct netent{
        char     *n_name;     // network
        char   **n_aliases; // alternate network name array pointer
        int      n_addrtype;  // address type
        uint32_t n_net        // network number
        ...
      }
    6 协议名字和协议编号之间进行映射。
      struct protoent* getprotobyname( const char *name );
      struct protoent* getprotobynumber( int proto );
      struct protoent* getprotoent( void );
      void setprotoent( int stayopen );
      void endprotoent( void );
      struct protoent{
        char     *p_name;      // protocol name
        char     **p_aliases;  // pointer to altername protocol name array
        int      p_proto;      // protocol number
        ...
      }
    7 函数getservent顺序扫描服务数据库。
      struct servent* getservbyname( const char *name, const char *proto );
      struct servent* getservbyport( int port, const char *proto );
      struct servent* getservent( void );
      void setservent( int stayopen );
      void endservent( void )
      struct servent{
        char        s_name;      // service name
        char        **s_aliases; // pointer to alternate service name array
        int         s_port;      // port name
        char        *s_proto;    // name of protocol
        ...
      }
    8 将主机名和服务名映射到一个地址。
      int getaddrinfo( const char *restrict host, const char *restrict service, const struct addrinfo *restrict hint, struct addrinfo **restrict res );
      void freeaddrinfo( struct addrinfo *ai );
      struct addrinfo{
        int              ai_flags;       // custemize behavior
        int              ai_family;      // address family
        int              ai_socktype;    // socket type
        int              ai_protocol;    // protocol
        socklen_t        ai_addrlen;     // length in bytes of address
        struct sockaddr  *ai_addr;       // address
        char             *ai_canonname;  // canonical name of host
        struct addrinfo  *ai_next;       // next in list
        ...
      }
    9 将返回的错误码转换成错误信息
      consr char *gai_strerror( int error );
    10 将地址转换成 主机名 和 服务名
      int getnameinfo( const struct sockaddr *restrict addr, socklen_t alen, char *restrict host, socklen_t hostlen, char *restrict service, socklen_t servlen, int flags );

    3:套接字 和 地址关联。

    1 绑定 关联地址 和 套接字。
      int bind( int sockfd, const struct sockaddr *addr, socklen_t len len );
      // 1 地址必须有效,且格式匹配。
      // 2 端口一般不小于1024.root权限用户除外。
      // 3 一般不允许多重绑定。
    2 查找 套接字对应的地址。
      int getsockname( int sockfd, struct sockaddr *restrict addr, socklen_t *restrict alenp );
    3 找到和套接字连接的对等方地址。
      int getpeername( int sockfd, struct sockaddr *restrict addr, socklen_t *restrict alenp );
    4 (请求服务端)建立连接。
      int connect( int sockfd, const struct sockaddr *addr, socklen_t len );
      // 1 参数addr:期望通信的服务器地址。
      // 2 应用程序必须能够处理connect函数返回的错误。
    5 (接收信息端)接收连接请求。
      int listen( int sockfd, int backlog );
    6 获得连接请求,并建立连接。
      int accept( int sockfd, struct sockaddr *restrict addr, socklen_t *restrict len );
      // 1 返回值:套接字描述符。

    4:数据传输。

    1 发送数据。
      ssize_t send( int sockfd, const void *buf, size_t nbytes, int flags );  // 套接字必须已经连接。
      // 1 返回成功,仅代表发送成功。接收错误不反馈。
      ssize_t sendto( int sockfd, const void *buf, size_t nbytes, int flags, const struct sockaddr *destaddr, socklen_t destlen );  // 可以在无连接套接字上发送信息。
      ssize_t sendmsg( int sockfd, const struct msghdr *msg, int flags, );  // 可以指定多重缓冲区传输数据。
    2 接收数据。
      ssize_t recv( int sockfd, void *buf, size_t nbytes, int flags );  //
      ssize_t recvfrom( int sockfd, void *restrict buf, size_t len, int flags, struct sockaddr *restrict addr, socklen *restrict addrlen );  // 得到数据发送者的原地址
      ssize_t recvmsg( int sockfd, struct msghdr *msg, int flags );  // 将接收数据送入多个缓冲区

    5:套接字选项。

    1 设置套接字选项。
      int setsockopt( int sockfd, int level, int option, const void *val, socklen_t len );
      // 1 参数level:标识选项应用协议。
    2 查看当前选项。
      int getsockopt( int sockfd, int level, int option, void *restrict val, socklen_t *restrict lenp );
      // 1 参数level:标识选项应用协议。

    6:带外数据。

    1 TCP中,判断是否已经到达紧急数据标记位置。
      int sockarmark( int sockfd );
      // 1 返回值:1 在标记处,0 不在标记处,-1 出错

    7:  UNIX域套接字。

    1 创建一对无命名的,相互连接的UNIX域套接字。(一般只用于UNIX域。)
      int socketpair( int domain, int type, int protocol, int sockfd[2] );   // 打开的为全双工管道。
      // 1 返回值:0 成功,-1 出错。
    2 sockaddr_un 结构体。
      struct sockaddr_un
      {
        sa_family_t   sun_family;     // AF_UNIX
        char          sun_path[108];  // pathname
      }   // OS:linux and solaris。 Head file name is "sys/un.h";

     三

  • 相关阅读:
    点击单元格(LinkToAction)获取Table行号和数据(Table篇一)
    金额和数量不显示0
    自定event事件之全局初始化中自动触发(二)
    自定event事件之手动触发(一)
    Python的requests如何同时post图片二进制流和json数据application/octet-stream
    树莓派点亮LED灯需要几行代码?3行。小孩子都能学会
    50元求解pyqt加载并显示pdf问题
    pyqt5加载pdf文档失败
    建个群,互相关心
    唉,十年前的沙雕照片
  • 原文地址:https://www.cnblogs.com/zheng39562/p/4270240.html
Copyright © 2020-2023  润新知