图中展示的交互流程如下:
(1)服务器根据地址类型(ipv4/ipv6)、socket类型,协议创建socket
(2)服务器为socket绑定IP地址和端口号
(3)服务器socket监听端口号请求,随时准备接收客户端发来的链接, 这时候服务器的socket并没有被打开
(4)客户端创建socket
(5)客户端打开socket,根据服务器的IP地址和端口号视图链接服务器socket
(6)服务器socket接收到客户端的socket请求,被动打开,开始接受客户端请求,知道客户端返回链接请求。这时候socket进入阻塞状态,。
所谓阻塞即为accept()方法一直到客户端返回链接信息才返回,开始接收下一个客户端的连接请求。
(7)客户端连接成功,想服务武发送连接状态信息
(8)服务器accept方法返回,连接成功
(9)客户端向socket写入信息
(10)服务器读取信息
(11)客户端关闭
(12)服务器关闭
仔细看就可以看出来这其实就是三次握手的过程,如下
1、socket函数
int socket(int domain,int type,int protocol)
参数介绍
(1)domain:协议族。常用的协议族有:AF_INET,AF_INET6,AF_LOCAL(UNIX的socket),AF_ROUTE协议族决定了socket的地址类型,比如AF_INET就是IPV4与16位端口号的组合,AF_LOCAL就是决定了要用一个绝对路径名作为地址 (2)type:制定了socket类型。常用的socket类型有:SOCK_STREAM,SOCK_DGRAM,SOCK_RAW,SOCK_PACKET,SOCK_SEQPACKET。 其中SOCK_STREAM表示提供面向连接的稳定数据传输,即TCP协议。SOCK_DGRAM表示使用不连接,不可靠的数据包连接 (3)protocol:指定协议。常用的协议有,IPPROTO_TCP,IPPTOTO_UDP,IPPROTO_SCTP,IPPROTO_TIPC等,他们分别对应TCP传输协议 UDP传输协议,STCP传输协议,TIPC传输协议
如果调用成功就返回新创建的套接字的秒速福,如果失败就返回INVALID_SOCKET(linux返回-1)。
2、bind函数
bind()函数就是把一个地址族中的特定地址赋给socket。
1 int bind(int sockfd,const struct sockaddr *addr,socklen_t addrlen)
参数描述
(1)sockfd:即socket描述字,它是通过socket()函数创建来唯一表示一个socket的。bind()函数就是将给这个描述字绑定一个名字 (2)addr:一个canst struct sockaddr*指针,指向要绑定给sockfd的协议地址。这个地址结构根据地址创建socket时的地址协议族的不同而不同 (3)addrlen:对应的是地址的长度
一般来说服务器在启动的时候就会有一个地址,用来提供服务,客户就通过他来连接。而客户端就不用指定,系统会自动分配一个端口号
和自身的IP地址组合。这就是为什么通常服务器端在调用Listen之前会调用bind();而客户端就不用调用,而是在connet()时由系统系统随机生成一个
函数执行成功返回值为0,反之SOCKET_ERROR
3、listen和connect函数
int listen(int sockfd,int backlog)int connect(int sockfd,const struct sockaddr *addr,socklen_t addrlen)
listen函数参数
(1)第一个参数为socket描述字(2)第二个参数为相应的socket的最大连接个数
connect函数参数
(1)第一个参数为socket描述字 (2)第二个服务器的socket地址 (3)第三个为socket地址的长度
4、accept函数
int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen)
参数描述
(1)服务器的socket的描述字(这个描述字是服务器开始调用socket()函数生成的,成为监听的socket描述字)(2)只想struct sockaddr *的指针,用来返回客户端的协议地址(3)协议地址的长度
如果成功就由内核自动生成的一个全新的描述字,代表与返回客户的TPC链接
5、read\write
ssize_t read(int fd,void *buf,size_t count)ssize_t write(int fd,const void *buf,size_t count)
(1)socket的描述字fd(2)缓冲区buf(3)缓冲区长度count
read成功时就返回实际所读的字节数,如果返回的值是-表示已经读到文件的结束了,小于0表示出现了错误
如果错误为EINTR说明是由中断引起的,如果为ECONNREST表示网络连接除了问题
wirte返回值大于0,表示写了部分或者是全部的数据,返回值小于0此时出现了错误。