UNP——第四章,TCP套接字编程

1.socket 函数

  family

AF_INET        IPv4
AF_INET6      IPv6
AF_LOCAL      Unix域
AF_ROUTE      路由套接字
AF_KEY          密钥套接字

  type

SOCK_STREAM        字节流
SOCK_DGRAM         数据报
SOCK_SEQPACKET   有序分组
SOCK_RAW              原始套接字

  AF_INET 和 AF_INET6 的 protocol

IPPROTO_TCP
IPPROTO_UDP
IPPROTO_SCTP

(2)AF_xxx 和 PF_xxx

  AF_ 表示地址族,PF_xxx 表示协议族,但实际上 AF_ 和 PF_ 相同。

 

2.connect

  connect 指定 目标套接字,

  connect 调用时,TCP 发送 SYN

  TCP接收到 ACK时,connect 返回。

  connect 前,可以不bind,内核会在connect 时随机分配原套接字。

  connect 开始时,TCP从 CLOSED --> SYN_SEND,成功时, SYN_SEND --> ESTABLISH

  每次 connect 失败后,都必须 close 套接字,并重新调用 socket。

 

3.bind

  设置源套接字地址,

  可以指定也可以不指定,不指定内核会分配,

  设置为0则为不指定,

  指定任意IP时,下面两种都一样,因为 INADDR_ANY == 0,大小端都一样

serv.sin_addr.s_addr = INADDR_ANY;
serv.sin_addr.s_addr = htonl(INADDR_ANY);

  bind 返回的常见错误是, EADDRINUSE (地址已使用)。

 

4.listen

  listen 初始化排队的最大连接个数。

  内核为套接字分配了两个队列:

    未完成连接队列,即正在进行三次握手的,这些套接字处于 SYN_RECV 状态。

    已完成连接队列,即已经完成三次握手的,这些套接字处于 ESTABLISHED 状态。

  backlog > 两队列总和

 

5.accept

  用于已连接队列头返回已连接。

  如果已连接队列为空,则进程随眠。

  accept 若成功,则返回内核重新分配的套接字。

 

6.典型的多进程并发服务器

for(;;) {
    connfd = accept(listenfd, NULL, NULL);
    if (fork() == 0) {
            close(listenfd);
            work();
            close(connfd);
    }  
    close(connfd);
}

父子进程都要 close 未用的套接字,以减少引用计数。

当 套接字关闭时,才会发出 FIN。

另外也避免了 文件描述符用尽。

 

7.close

减少套接字引用计数,当引用计数为0,则关闭套接字。

应用程序无法通过套接字继续读写操作。

但TCP会将剩余的数据进行收发。

 

8.getsockname 和 getpeername

通过 文件描述符,获得 套接字对信息。

用于子进程 exec 后,需要获得 父进程时的套接字对信息,因为套接字信息在内核区,不会被exec后覆盖,所以子进程只要获得 文件描述符即可(可通过命令行参数获得)

你可能感兴趣的:(UNP——第四章,TCP套接字编程)