基本TCP客户-服务器程序的套接口函数如下图:
1、socket函数
原型:#include<sys/socket.h>
int socket(int family, int type, int protocol); 返回值:非负描述符--成功, -1--出错;
作用:指定期望的通信协议接口(TCP或UDP或unix域字节协议等)
family 指明协议簇
族 | 解释 |
AF_INET | IPv4协议 |
AF_INET6 | IPv6协议 |
AF_LOCAL | Unix与协议 |
AF_ROUTE | 路由套接口 |
AF_KEY | 密钥套接口 |
类型 | 解释 |
SOCK_STREAM | 字节流套接口 |
SOCK_DGRAM | 数据包套接口 |
SOCK_RAW | 原始套接口 |
2、connect函数
原型:#include<sys/socket.h>
int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);返回值:0---成功,-1----出错;
作用:客户端用connect 函数建立一个与TCP服务器的连接;
参数:sockfd,套接口描述字;
servaddr,套接口地址结构的指针,该地址结构需要包含服务器IP地址和端口号;
addrlen, 套接口地址结构的大小;
关于connect出错返回的几种情况:
- 如果TCP客户端没有收到SYN分节的响应,则返回ETIMEDOUT。
- 如果对客户的SYN的响应是RST,则表明该服务器主机在我们指定的端口上没有进程在等待与之连接,这称之为硬错,客户端接到RST,立即返回错误ECONNREFUSED;
- 如果某客户端发出的SYN在中间的路由器上引发了一个目的地不可达的ICMP错误,这称之为软错,客户端按时间间隔继续发送SYN,在规定时间仍未收到响应,则返回EHOSTUNREACH;
3、bind函数
原型:#include<sys/socket.h>
int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);
返回值:0---成功,-1----出错;
作用:给套接口分配一个本地协议地址;
参数:sockfd,套接口描述字;
myaddr,特定于协议的地址结构的指针,对于TCP,可以指定一个IP地址,一个端口号;
addrlen,第二个参数地址结构的长度;
4、listen函数
原型:#include<sys/socket.h>
int listen(int sockfd, int backlog);
返回值:0---成功,-1---出错;
作用 : 将未连接的套接口转换成被动套接口,指示内核应接受此套接口的连接请求;第二个参数规定了次套接口排队的最大连接数;
参数:sockfd,套接口描述字;
backlog,套接口排队的最大连接数;
对与第二个参数backlog的理解:
- 未完成连接队列,为每个已由客户端发出并到达服务器,服务器正在等待完成相应TCP三路握手过程的SYN分节开设一个条目,这些套接口都处于SYN_RCVD;
- 已完成队列:为每个已完成TCP三路握手过程的客户开设一个条目,这些套接口都处于ESTABLISHED状态;
关系如下图:
5、accept函数
原型:#include<sys/socket.h>
int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);
返回值:非负描述符---成功,-1----出错;
作用:有服务器调用,从已完成连接队列头返回下一个已完成连接,若已完成连接队列为空,则进程睡眠。
参数:sockfd,套接口描述字;
cliaddr,客户进程协议地址;
addrlen,第二个参数,客户进程协议地址的长度;
6、close函数
原型:#include<unistd.h>
int close(int sockfd);
作用:将套接口坐上“已关闭”标记,并立即返回到进程;