还原客户端send 0字节,服务端主动关闭后,客户端send 仍然返回0的全过程
注:客户端和服务端都是非阻塞模式
### 四次挥手过程图示(客户端和服务器都可以主动发出断开连接)
参考:
TCP三次握手和四次挥手及wireshark抓取 - elephantcc - 博客园
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S7SD1Hvk-1596600866827)(file:///Users/chen/Library/Application%20Support/marktext/images/2020-08-05-10-22-12-image.png)]
### 服务端代码:
/**
* 验证recv函数接受0字节的行为,server端,server_recv_zero_bytes.cpp
* zhangyl 2018.12.17
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <iostream>
#include <string.h>
#include <vector>
int main(int argc, char* argv[])
{
//1.创建一个侦听socket
int listenfd = socket(AF_INET, SOCK_STREAM, 0);
if (listenfd == -1)
{
std::cout << "create listen socket error." << std::endl;
return -1;
}
//2.初始化服务器地址
struct sockaddr_in bindaddr;
bindaddr.sin_family = AF_INET;
bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);
bindaddr.sin_port = htons(3000);
if (bind(listenfd, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) == -1)
{
std::cout << "bind listen socket error." << std::endl;
close(listenfd);
return -1;
}
//3.启动侦听
if (listen(listenfd, SOMAXCONN) == -1)
{
std::cout << "listen error." << std::endl;
close(listenfd);
return -1;
}
int clientfd;
struct sockaddr_in clientaddr;
socklen_t clientaddrlen = sizeof(clientaddr);
//4. 接受客户端连接
clientfd = accept(listenfd, (struct sockaddr *)&clientaddr, &clientaddrlen);
if (clientfd != -1)
{
while (true)
{
char recvBuf[32] = {0};
//5. 从客户端接受数据,客户端没有数据来的时候会在 recv 函数处阻塞
int ret = recv(clientfd, recvBuf, 32, 0);
if (ret > 0)
{
std::cout << "r