zoukankan      html  css  js  c++  java
  • 什么是套接口?

    什么是套接口?socket、套接口、套接口描述符之间的关系

      UNP 的译者在 p6 中的译注中提到:socket 一词应该译成“套接口”,理由如下:首先,作为网络编程 API 之一的套接口(sockets.注意这种用法总是采用复数形式,例如 sockets API、sockets library)跟 XTI 一样,是应用层到传输层或其他协议层的访问接口。其次,具体使用的套接口时与 unix 管道的某一端类似的东西,我们既可以往这个“口”写数据,也可以从这个“口”读取数据。最后,套接口函数使用套接口描述字访问具体的套接口,如果把套接口描述字的简称 socketfd 译成“套接字”倒比较合适。从这个意义上来讲,一个套接口可以对应多个套接字,因为 unix 的描述字既可以复制,也可以继承,反过来,一个套接字对应且只对应一个套接口。

    如何创建套接口?

      unix下通过 socket 函数创建套接口,该函数原型是:

      int socket(int family, int type, int protocol)。

      其中,family 参数指明协议族,它是 AF_INET(IPv4 协议)、AF_INET6(IPv6)协议、AF_LOCAL()、AF_ROUTE(路由套接口)、AF_KEY(密钥套接口)中的一种。

      其中, type 指明套接口类型,它是SOCK_STREAM(字节流套接口)、SOCK_DGRAM(数据报套接口)、SOCK_SEQPACKET(有序分组套接口)、SOCK_RAW(原始套接口)中的一个。

      其中,protocol 是 IPPROTO_TCP( TCP 协议)、IPPROTO_UDP( UDP 协议)、IPPROTO_SCTP(SCTP协议)中的一种。

      如果创建成功返回套接口描述符,简称套接字

    套接口用来做什么?

       在客户端:通过 connet() 用来与服务器建立连接。connet() 函数原型如下:

      int connec(int sockfd, const struct socktaddr *servaddr, socklen_t addrlen); 

      其中,sockfd 就是套接口描述符(用来描述套接口)。

      其中,servaddr 是套接口地址结构,这个结构用来指定 connect() 要连接的服务器的 IP 和 端口号。

      其中,addrlen 时套接口地址结构的大小。

      由于 connect() 函数要在客户端与服务器端建立连接,所以在调用 connect() 的时候会激发三次握手:1.主动请求连接方向被动请求连接方发送一个 SYN 分节,此时主动方处于 SYN_SENT 状态,如果被动方收到 SYN 分节,并返回一个 ACK 和 一个自己的 SYN,此时被动方处于SYN_RCVD 状态。调用 connect() 的主动方接受到被动方回应的 ACK 后,connect() 返回 0(表示成功),否则回返回 -1(出错)。connect() 成功返回后,主动方处于 ESTABLISHED 状态,表示连接已经建立。并向被动方发送一个 ACK(用来回应被动方发送的 SYN 分节)。

      在服务器端:在服务器端稍微复杂一点点,要比客户端多两个步骤:

      1、用 bind() 函数将一个本地协议地址赋予一个套接口。对于网际地址时 32 为的 IPV4地址或 128 位的 IPV6 地址与 16 位的 TCP 或 UDP 端口号的组合。bind() 函数原型如下:

      int bind(int sockfd,const struct sockaddr *myaddr ,socklen_t addrlen);

      bind() 函数的原型和 connect() 一样,但作用还是有差别的。connect() 是将 sockfd 与套接口地址结构对应的服务器建立连接,而 bind() 是将 sockfd 与本地套接口地址结构进行绑定。

      2、调用 listen() 函数将套接口变成监听套接口,listen() 原型如下:

      int listen(int sockfd, int backlog);

      其作用有两个:a.将一个未连接的套接口转换成一个被动套接口,只是内核应该接受指向该套接口的的连接请求。并使套接口从 closed 状态转换到 LISTEN 状态。

             b.listen() 的第二个参数规定了内核应该为相应套接口排队的最大连接个数。

      3、调用 accept() 函数在监听套接口(由listen()转化的套接口描述符)接受新连接的到达,如果没有新连接到达那么进程就投入睡眠(假设套接口为缺省的阻塞方式)。上面我说过,客户端是通过 connect() 来建立连接的,在客户端收到服务器端的 ACK时,connect() 函数返回,并且发送一个 ACK,当服务器端接受到这个 ACK 时,此时三次握手完成。连接建立完成,新连接到达,此时,服务器端的监听套接口转换成 ESTABLISHED 状态,accept() 成功返回。

      accept() 函数原型如下:int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);

      其中, sockfd 时监听套接口,cliaddr 是已连接的对端进程(客户)的协议地址。addrlen 是值-结果参数,是内存存在该套接口地址结构(cliaddr)的确切字节数。

      accept() 返回非负描述符,我们称其为已连接套接口描述符。一定要区别监听套接口描述符和已连接套接口描述符,一般来说服务器在其生命周期内只创建一个监听套接口描述符,而内核为每个由服务器进程接受的客户连接创建一个已连接套接口。

  • 相关阅读:
    [转]SVN服务器搭建和使用(二)
    [转]SVN服务器搭建和使用(一)
    BZOJ 2049 Sdoi2008 Cave 洞穴勘测
    BZOJ 1589 Usaco2008 Dec Trick or Treat on the Farm 采集糖果
    BZOJ 2796 POI2012 Fibonacci Representation
    BZOJ 2115 Wc2011 Xor
    BZOJ 3105 CQOI2013 新Nim游戏
    BZOJ 2460 Beijing2011 元素
    BZOJ 3687 简单题
    BZOJ 1068 SCOI2008 压缩
  • 原文地址:https://www.cnblogs.com/zhuwbox/p/3836331.html
Copyright © 2011-2022 走看看