This is my study note of socket.

什么是socket——“套接字”

1
2
socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“open->write/open->close”模式来操作。
可以理解为:socket是一种特殊的文件,一些socket函数就是对其进行的操作。

socket传输方式

  • SOCK_STREAM
    1
    表示面向连接的数据传输方式。
  • SOCK_DGRAM
    1
    表示无连接的数据传输方式。

socket函数

  • int socket(int af, int type, int protocol)
    1
    2
    3
    af:为地址簇,也就是IP地址类型,常用的有AF_INET(IPV4)和AF_INET6(IPV6)。
    type:选择SOCK_STREAM或SOCK_DGRAM。
    protocol:表示IPPROTO_TCP或IPPTOTO_UDP分别表示TCP和UDP。
  • sockaddr_in
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    struct sockaddr_in
    {
    sa_family_t sin_family;
    uint16_t sin_port;
    struct in_addr sin_addr;
    char sin_zero[8];
    };
    sin_family:地址簇AF_INET或AF_INET6
    sin_port:表示16位TCP/UDP端口号
    sin_addr:32位IP地址
    sin_zero[8]:不使用
  • int bind(int sock, struct sockaddr *addr, socklen_t addrlen)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    sock:表示socket描述符
    addr:表示sockaddr结构体变量的指针
    addrlen:表示addr变量的大小,由sizeof计算得出

    int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    serv_addr.sin_port = htons(1234);
    bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
  • int connect(int sock, struct sockaddr *ser_addr, socklen_t addrlen);
    1
    建立连接。
  • int listen(int sock, int backlog)
    1
    2
    3
    4
    5
    sock:表示进入监听状态的套接字
    backlog:为请求队列的最大长度,如果将 backlog 的值设置为 SOMAXCONN,就由系统来决定请求队列长度,这个值一般比较大,
    可能是几百,或者更多。
    所谓被动监听,是指当没有客户端请求时,套接字处于“睡眠”状态,只有当接收到客户端请求时,套接字才会被“唤醒”来响应请求。
    当请求队列满时,就不再接收新的请求,对于 Linux,客户端会收到 ECONNREFUSED 错误。
  • ssize_t write(int fd, const void *buf, size_t nbytes)
    1
    2
    3
    fd:要写入的文件描述符
    buf:要写入数据的缓冲地址
    nbytes:要写入的字节数
  • ssize_t read(int fd, void *buf, size_t nbytes)
    1
    2
    3
    fd:要读取的文件描述符
    buf:要读取数据的缓冲地址
    nbytes:要读取的字节数