网络编程
什么是网络编程
网络编程就是在操作系统封装的TCP/IP协议栈的基础上,使用系统内核提供的socket api 进行应用开发.
| TCP/IP四层协议栈 |
|---|
| 应用层 |
| 传输层 |
| 网络层 |
| 链路层 |
网络编程的交互过程

| TCP server | 说明 |
|---|---|
| socket() | 创建基于ipv4 or ipv6的TCP socket数据结构,并和一个文件相绑定,同时给我们返回一个socketfd,供后续函数使用 |
| bind() | 将具体的IP PORT绑定到该socket数据结构上 |
| listen() | 将socket转为已监听套接字。此时服务器可被动连接了 |
| accept() | 等待全连接队列里有socket,若在全连接队列里发现了socket,会为它创建一个 新文件并分配新的acceptfd,这个文件被称为已连接socket 此时,服务器与客户端就可以收发数据了 |
| read() | 读取acceptfd相关的socket接收缓冲区,如果socket接收缓冲区有数据,read()返回,否则read()会阻塞,直到socket接收缓冲区中有了数据。这个接收数据的过程是由内核TCP/IP协议栈实现的。 |
| write() | 写入socket发送缓冲区,如果此时发送缓冲区是满的,write ()则会被阻塞。写入socket发送缓冲区的数据,由内核TCP/IP协议执行发往对端 |
| close() | 完成四次挥手的第二阶段 |
| TCP client | 说明 |
|---|---|
| socket() | 创建基于ipv4 or ipv6的TCP socket数据结构,并和一个文件相绑定,同时给我们返回一个socketfd,供后续函数使用 |
| connect() | 发起主动连接。 客户端内核协议栈向服务器发送三次握手的第一步 SYN;当服务器收到这个 SYN,会把该socket放到半连接队列,并向客户端发送ACK,SYN。当客户端接受到这个 ACK,SYN,会向服务器发送ACK。此时客户端connect()函数返回,客户端认为三次握手完成。当服务器收到客户端传来的 ACK,则将内核中的SOCKET放入全连接队列,服务器端accept()函数返回 |
| write() | 写入socket发送缓冲区,如果此时发送缓冲区是满的,write ()则会被阻塞。写入socket发送缓冲区的数据,由内核TCP/IP协议执行发往对端 |
| read() | 读取sokcetfd相关的socket接收缓冲区,如果socket接收缓冲区有数据,read()返回,否则read()会阻塞,直到socket接收缓冲区中有了数据。这个接收数据的过程是由内核TCP/IP协议栈实现的。 |
| close() | 完成四次挥手的第一阶段。 内核协议协议栈会给服务器发送 FIN,告知本端已经关闭;服务端收到客户端的 FIN,内核协议栈会给客户端回复ACK,同时read()调用会返回0,这样服务器就知首客户端关闭连接了。这个时候,服务器会调用 close(),开启四次挥手的第二个阶段,向客户端发送一个FIN。客户端收到该 FIN后,内核协议栈回复ACK,并进入TIME_WAIT状态,等待2MSL,也就是60秒 |
read()返回值:
大于0,读取成功;
=0,表示对端关闭连接,此时也要调用close()关闭连接;
<0,表示操作产生错误
write()返回值:
大于等于0,表示写了多少字节的数据,0表示啥也没写
<0,表示操作产生错误
常见问题
-
客户端调用close()一定会发送FIN吗?
不一定。这要看该socketfd的引用计数器有没有达到0。如有多个进程共享这个socket文件,其中一个进程close(),并不会向对端发送FIN。
-
假如一方断网了,不能进行四次挥手,服务器会怎么处理?
- 未断开的一端,会保持
established状态 - 未断开一端
开启keepalive,则会定时向对方发送TCP保活segment,对方协议栈回复RST。这样未端开端就会知道对方的状态,若对方已离线,就关闭本端连接。 - 未断开一端
未开启keepalive,只有在向对方发送数据时,会得到错误提示Connection reset by peer,再次向对对方写数据,则会产生EPIPE错误。 - 所以为了应对这种情况,服务器会在
应用层做保活心跳,对于断开的client 做定时踢掉处理。
-
客户端发送FIN之后,会发生什么?
- TCP是全双工通信,客断端发送
FIN,就是告诉服务器它不再发送数据了,也不要在acceptefd上读数据了,若SERVER再次进行读取,只会得到0,也就是EOF.(四次挥手的第一阶段) - 若SERVER还想给CLIENT发送数据,就继续给CLIENT发送就可以了。这也是常说的
TCP半关闭状态。 - 如果SERVER也不需要再向CLIENT发送数据了,也需要调用close,向CLIENT发送FIN。(
四次挥手的第二阶段)
浙公网安备 33010602011771号