zoukankan      html  css  js  c++  java
  • 基本TCP Sockets编程

    一、socket 函数

    #include <sys/socket.h>
      int socket (int family, int type, int protocol);
          Returns: non-negative descriptor if OK, -1 on error
    • family参数指明协议族(协议域)。它们分别是:   AF_INET——IPv4 协议、 AF_INET6——IPv6协议 、 AF_LOCAL(AF_UNIX)——Unix域协议 、AF_ROUTE——路由套接口协议、AF_KEY——密钥套接口协议
    •  type指明套接口类型。它们分别是:  SOCK_STREAM——字节流套接口、SOCK_DGRAM——数据报套接口、SOCK_SEQACKET——有序分组套接口、SOCK_RAW——原始套接口
    • protocol指明某个协议类型常值,或者也可以设置为0,以选择所给定family和type组合的系统缺省值。它们分别是:IPPROTO_TCP——TCP传输协议、IPPROTO_UDP——UDP传输协议、IPPROTO_STCP——STCP传输协议

    family和type参数的组合如下:

      

     socket成功时会返回一个小的非负整数值,它与文件描述字一致,我们成为套接字(socket descriptor)。AF_前缀表示地址族,PF_前缀表示协议族。不过这两个东西是相等的,所以用哪个都行。


    二、connect函数

      connect函数用于 TCP客户端与TCP服务端建立连接

    1 #include <sys/socket.h>
    2 int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);
    3                 Returns: 0 if OK, -1 on error                
    • sockfd是套接字。
    • servaddr是指向套接字地址结构的指针
    • adrlen是套接字地址结构的大小
    • socket address structrue(套接字地址)必须含有IP地址和端口号

      client在调用connect之前不必非得调用bind函数,因为如果需要的话,内核会确定源IP地址,并选择一个临时端口作为源端口。调用conect函数将initiates TCP的三路握手过程。

    出错返回有以下情况:

    • 如果client TCP没有收到SYN segment的响应,那么ETIMEDOUT将返回。
    • 如果服务器TCP对client的响应是RST,这说明服务器在我们指定的端口上并没有进程在等待和它连接,这是一个hard error,当客户收到RST后,就返回ECONNREFUSED
    • 若客户发出的SYN在中间的某个路由器上引发了"destination unreachable”错误,则继续发送SYN信号,如果在某个规定时间内,仍未收到响应,则把保存的消息作为EHOSTUNREACH或者ENETUNREACH错误返回。

    如果connect失败,这个socket就不能用了,必须关闭。我们不能用这样的套接口再次调用connect函数。

     


    三、bind函数 

      bind函数指定一个本地协议地址分配给一个未命名的socket。使用Socket函数创建的那些套接字初始化是没有命名的,它们只有通过地址族才能被识别到,对于网络协议:协议地址是32位的IPv4地址或128位的IPv6地址与16位的TCP或UDP的端口号的组合。调用bind函数,可以指定一个端口号、一个IP地址、也可以两者都指定、也可以都不指定。

    #include <sys/socket.h>
      int bind (int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);
                Returns: 0 if OK,-1 on error
    • sockfd是套接字
    • myaddr是指向特定协议地址结构的指针
    • addrlen是该地址结构的长度
    • 如果一个TCP client或者server 没有绑定端口,kernel在调用connect或listen时,就会选择一个临时端口。内核选择临时端口,对于TCP客户来说是正常的
    • 一个process可以bind特定的IP地址到它的socket,这个IP地址一定属于其所在主机的网络接口之一。对于TCP,这就为该socket发送的IP数据报指定了源IP地址;对于TCP服务器,这就限定了该套接口只接收那些目的地为这个IP地址的客户连接。
    • 如果TCP没有把IP地址绑定到它的套接口上,内核就会把客户发送的SYN的宿IP地址作为服务器的源IP地址。

    四、listen函数

      TCP服务器调用listen函数,主要有两个作用:

    • 当socket函数创建一个socket时,它被指定为active socket(主动套接口),也就是说它是一个将会调用connect发起连接的客户套接口。listen函数将未连接的套接口转换为一个passive socket(被动套接口),指示内核接受指向socket 的到来的连接请求。调用TCP将sockets的状态从CLOSED转换为LISTEN状态
    • 第二个参数指定了内核应该为这个socket排队的最大连接数。
    #include <sys/socket.h>
    #int listen (int sockfd, int backlog);
          Returns: 0 if OK, -1 on error

       这个函数应该在调用socket和bind函数之后,在调用accept函数之前。

     内核为每个给定的监听套接口维护两个队列:

    • 未完成连接队列(incomplete connection queue ):每个这样的SYN分节对应其中一项,已知由某个服务器发出并到达服务器,而服务器正在等待完成相应的TCP三路握手过程。这些套接口处于TCP_RCVD状态。
    • 已完成连接状态(completed comnection queue): 每个已完成TCP三路握手过程的客户对应其中一项,这些套接口处于ESTABLISHED状态。

     

    •  当来自client的SYN到达时,TCP在未完成连接队列中创建一个新项,然后响应以三路握手的第二个分节(服务器的SYN响应,其中捎带对客户SYN的ACK)。这一项一直保留在未完成队列,直到三路握手的第三个分节(客户对服务器SYN的ACK)达到或者该项超时。
    • 如果三路握手正常,该项就从未完成队列移动到已完成队列的对尾。
    • 当进程调用accept时,已完成队列中的队头项将返回给进程,或者如果该队列为空,那么进程将被投入睡眠,直到TCP在该队列中放入一项才唤醒它。
    • 在三路握手正常完成的前提下,未完成连接队列中的任何一项在其中存留的时间就是一个RTT(客户到服务器的往返时间)

     五、accept函数

      TCP 服务器调用accept函数,从一个已完成队列的队头(complete connection queue)返回一个已完成的连接。如果已完成连接队列为空,那么进程被投入睡眠

       

    #include <sys/socket.h>
      int accept (int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);
        Returns: non-negative descriptor if OK, -1 on error
    • cliaddr:返回已连接对端进程(client)协议地址
    • addrlen:value-result(值-结果参数),调用前是*cliaddr所指的套接口地址的长度;返回时,其整数值为内核存在该套接口地址结构内的确切字节数。

    如果accept成功,那么其返回值是由内核自动升成的一个全新描述字,代表与client的TCP连接。我们称这个函数的第一个参数是listening socket(监听套接口),函数返回的是connected socket(已连接套接口)

    服务器在仅仅只创建一个listening socket,它存在于服务器的整个生命周期内。内核为每个服务器进程已接受的客户创建一个已连接套接口。当服务器完成对于某个给定客户的服务时,相应的已连接套接口的服务就被关闭。  

       本函数最多返回三个值:

    • 一个既可能是新套接口描述字也可能是出错提示整数的整数,客户进程的协议地址(由cliaddr所指)以及该地址的大小(由addrlen指针所指),如果对客户协议地址不感兴趣,可以把cliaddr和addrlen均置为空指针。

    六、并发服务器 

       

     

    陈小洁的三只猫
  • 相关阅读:
    ExtJs五(ExtJs Mvc登录优化)
    Scott Mitchell的ASP.NET2.0数据指南中文版索
    sql server2005分页存储过程
    Microsoft Visual Studio 2005的导入和导出设置
    ASP.NET2.0 ObjectDataSource的使用详解(1)
    存储过程编写经验和优化措施
    .net面试题大全,绝大部分面试题
    CodeSmith 4 Release 注册方法
    Page.ClientScript.RegisterStartupScript() 方法与Page.ClientScript.RegisterClientScriptBlock() 方法
    XHTML概述
  • 原文地址:https://www.cnblogs.com/ccpang/p/11398589.html
Copyright © 2011-2022 走看看