C/S程序的通常流程和基本socket函数(七)

1、基于TCP协议的网络程序服务器



服务器调用socket()、bind()、listen()完成初始化后,调用accept()阻塞等待,处于监听端口的状态,客户端调用socket()初始化后,调用connect()发出SYN段并阻塞等待服务器应答,服务器应答一个SYN-ACK段,客户端收到后从connect()返回,同时应答一个ACK段,服务器收到后从accept()返回。网络


数据传输的过程:
dom

创建链接后,TCP协议提供全双工的通讯服务,可是通常的客户端/服务器程序的流程是由客户端主动发起请求,服务器被动处理请求,一问一答的方式。所以,服务器从accept()返回后马上调用read(),读socket就像读管道同样,若是没有数据到达就阻塞等待,这时客户端调用write()发送请求给服务器,服务器收到后从read()返回,对客户端的请求进行处理,在此期间客户端调用read()阻塞等待服务器的应答,服务器调用write()将处理结果发回给客户端,再次调用read()阻塞等待下一条请求,客户端收到后从read()返回,发送下一条请求,如此循环下去。socket


若是客户端没有更多的请求了,就调用close()关闭链接,就像写端关闭的管道同样,服务器的read()返回0,这样服务器就知道客户端关闭了链接,也调用close()关闭链接。注意,任何一方调用close()后,链接的两个传输方向都关闭,不能再发送数据了。若是一方调用shutdown()则链接处于半关闭状态,仍可接收对方发来的数据。函数


在学习socket API时要注意应用程序和TCP协议层是如何交互的: 学习

*应用程序调用某个socket函数时TCP协议层完成什么动做,好比调用connect()会发出SYN段spa

 *应用程序如何知道TCP协议层的状态变化,好比从某个阻塞的socket函数返回就代表TCP协议收到了某些段,再好比read()返回0就代表收到了FIN段blog


补充一下,其实TCP 共有11种状态,上图没有出现的CLOSING 状态,当双方同时关闭链接时会出现此状态,替换掉FIN_WAIT2状态。接口

有机状态图:
图中有三种不一样的箭头。粗实线箭头表示对客户进程的正常变迁。粗虚线箭头表示对服务器进程的正常变迁。另外一种细线箭头表示异常变迁。
队列




须要注意: TCP 链接必须通过时间 2MSL 后才真正释放掉。由于:为了保证 A(客户) 发送的最后一个 ACK 报文段可以到达 B(服务器);防止“已失效的链接请求报文段”出如今本链接中。A 在发送完最后一个 ACK 报文段后,再通过时间 2MSL(时间等待计时器),就可使本链接持续的时间内所产生的全部报文段,都从网络中消失。这样就可使下一个新的链接中不会出现这种旧的链接请求报文段。


2、基本socket函数

一、socket函数

包含头文件<sys/socket.h>
功能:建立一个套接字用于通讯
原型:int socket(int domain, int type, int protocol);
参数
domain :指定通讯协议族(protocol family),AF_INET、AF_INET六、AF_UNIX等
type:指定socket类型,流式套接字SOCK_STREAM,数据报套接字SOCK_DGRAM,原始套接字SOCK_RAW
protocol :协议类型,IPPROTO_TCP等;通常由前两个参数就决定了协议类型,设置为0便可。
返回值:成功返回非负整数, 它与文件描述符相似,咱们把它称为套接口描述字,简称套接字。失败返回-1


二、bind函数

包含头文件<sys/socket.h>
功能:绑定一个本地地址到套接字
原型:int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数
sockfd:socket函数返回的套接字
addr:要绑定的地址
addrlen:地址长度
返回值:成功返回0,失败返回-1



三、listen函数

包含头文件<sys/socket.h>
功能:将套接字用于监听进入的链接
原型:int listen(int sockfd, int backlog);
参数
sockfd:socket函数返回的套接字
backlog:已完成三次握手的最大链接个数
返回值:成功返回0,失败返回-1

通常来讲,listen函数应该在调用socket和bind函数以后,调用函数accept以前调用。
对于给定的监听套接口,内核要维护两个队列:
一、已由客户发出并到达服务器,服务器正在等待完成相应的TCP三路握手过程
二、已完成链接的队列



四、accept函数

包含头文件<sys/socket.h>
功能:从已完成链接队列返回第一个链接,若是已完成链接队列为空,则阻塞。
原型:int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
参数
sockfd:服务器套接字
addr:将返回对等方的套接字地址
addrlen:返回对等方的套接字地址长度
返回值:成功返回非负整数,失败返回-1


五、connect函数

包含头文件<sys/socket.h> 功能:创建一个链接至addr所指定的套接字 原型:int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 参数 sockfd:未链接套接字 addr:要链接的套接字地址 addrlen:第二个参数addr长度 返回值:成功返回0,失败返回-1