基本 TCP 套接字编程讲解(1)


基本 TCP 套接字编程讲解

基于 TCP 的套接字编程的所有客户端和服务器端都是从调用socket 开始,它返回一个套接字描述符。客户端随后调用connect 函数,服务器端则调用 bind、listen 和accept 函数。套接字通常使用标准的close 函数关闭,但是也可以使用 shutdown 函数关闭套接字。下面针对套接字编程实现过程中所调用的函数进程分析。以下是基于 TCP 套接字编程的流程图:

socket 函数

套接字是通信端点的抽象,实现端对端之间的通信。与应用程序要使用文件描述符访问文件一样,访问套接字需要套接字描述符。任何套接字编程都必须调用socket 函数获得套接字描述符,这样才能对套接字进行操作。以下是该函数的描述:

  1. /* 套接字 */   
  2.    
  3. /*  
  4.  * 函数功能:创建套接字描述符;  
  5.  * 返回值:若成功则返回套接字非负描述符,若出错返回-1;  
  6.  * 函数原型:  
  7.  */   
  8. #include <sys/socket.h>   
  9.    
  10. int socket(int family, int type, int protocol);   
  11. /*  
  12.  * 说明:  
  13.  * socket类似与open对普通文件操作一样,都是返回描述符,后续的操作都是基于该描述符;  
  14.  * family 表示套接字的通信域,不同的取值决定了socket的地址类型,其一般取值如下:  
  15.  * 1)AF_INET         IPv4因特网域  
  16.  * 2)AF_INET6        IPv6因特网域  
  17.  * 3)AF_UNIX         Unix域  
  18.  * 4)AF_ROUTE        路由套接字  
  19.  * 5)AF_KEY          密钥套接字  
  20.  * 6)AF_UNSPEC       未指定  
  21.  *  
  22.  * type确定socket的类型,常用类型如下:  
  23.  * 1)SOCK_STREAM     有序、可靠、双向的面向连接字节流套接字  
  24.  * 2)SOCK_DGRAM      长度固定的、无连接的不可靠数据报套接字  
  25.  * 3)SOCK_RAW        原始套接字  
  26.  * 4)SOCK_SEQPACKET  长度固定、有序、可靠的面向连接的有序分组套接字  
  27.  *  
  28.  * protocol指定协议,常用取值如下:  
  29.  * 1)0               选择type类型对应的默认协议  
  30.  * 2)IPPROTO_TCP     TCP传输协议  
  31.  * 3)IPPROTO_UDP     UDP传输协议  
  32.  * 4)IPPROTO_SCTP    SCTP传输协议  
  33.  * 5)IPPROTO_TIPC    TIPC传输协议  
  34.  *  
  35.  */   

connect 函数

在处理面向连接的网络服务时,例如 TCP ,交换数据之前必须在请求的进程套接字和提供服务的进程套接字之间建立连接。TCP 客户端可以调用函数connect 来建立与 TCP 服务器端的一个连接。该函数的描述如下:

  1. /*  
  2.  * 函数功能:建立连接,即客户端使用该函数来建立与服务器的连接;  
  3.  * 返回值:若成功则返回0,出错则返回-1;  
  4.  * 函数原型:  
  5.  */   
  6. #include <sys/socket.h>   
  7.    
  8. int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);   
  9. /*  
  10.  * 说明:  
  11.  * sockfd是系统调用的套接字描述符,即由socket函数返回的套接字描述符;  
  12.  * servaddr是目的套接字的地址,该套接字地址结构必须包含目的IP地址和目的端口号,即想与之通信的服务器地址;  
  13.  * addrlen是目的套接字地址的大小;  
  14.  *  
  15.  * 如果sockfd没有绑定到一个地址,connect会给调用者绑定一个默认地址,即内核会确定源IP地址,并选择一个临时端口号作为源端口号;  
  16.  */   

TCP 客户端在调用函数 connect 前不必非得调用 bind 函数,因为内核会确定源 IP 地址,并选择一个临时端口作为源端口号。若 TCP 套接字调用connect 函数将建立 TCP 连接(执行三次握手),而且仅在连接建立成功或出错时才返回,其中出错返回可能有以下几种情况:

若 TCP 客户端没有收到 SYN 报文段的响应,则返回 ETIMEOUT 错误;

若客户端的 SYN 报文段的响应是 RST (表示复位),则表明该服务器主机在我们指定的端口上没有进程在等待与之连接。只是一种硬错误,客户端一接收到 RST 就立即返回ECONNERFUSED 错误;

RST 是 TCP 在发生错误时发送的一种 TCP 报文段。产生 RST 的三个条件时:

目的地为某端口的 SYN 到达,然而该端口上没有正在监听的服务器;

TCP 想取消一个已有连接;

TCP 接收到一个不存在的连接上的报文段;

若客户端发出的 SYN 在中某个路由器上引发一个目的地不可达的 ICMP 错误,这是一个软错误。客户端主机内核保存该消息,并在一定的时间间隔继续发送 SYN (即重发)。在某规定的时间后仍未收到响应,则把保存的消息(即 ICMP 错误)作为EHOSTUNREACH 或ENETUNREACH 错误返回给进行。




相关内容