阻塞
即为数据无法添加或者删除,一直开在此处,直到数据可以添加或者删除的时候;
如果是发送阻塞【send】,即为操作系统内的缓冲区满了,无法继续添加到操作系统内的缓冲区,会阻塞在当下,直到操作系统内的缓冲区有空闲为止;
如果是接收阻塞【recv】,即为操作系统内的缓冲区空了,无法继续获取到操作系统内的缓冲区的数据,会阻塞在当下,直到操作系统内的缓冲区有缓冲数据为止;
示例
服务端
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <iostream>
#include <string.h>
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;
}
while (true)
{
struct sockaddr_in clientaddr;
socklen_t clientaddrlen = sizeof(clientaddr);
//4. 接受客户端连接
int clientfd = accept(listenfd, (struct sockaddr *)&clientaddr, &clientaddrlen);
if (clientfd != -1)
{
//只接受连接,不调用recv收取任何数据
std:: cout << "accept a client connection." << std::endl;
}
}
//7.关闭侦听socket
close(listenfd);
return 0;
}
客户端
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <iostream>
#include <string.h>
#include <sys/uio.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#define SERVER_ADDRESS "127.0.0.1"
#define SERVER_PORT 3000
#define SEND_DATA "helloworld"
int setnonblocking(int fd)
{
int old_option = fcntl(fd, F_GETFL);
int new_option = old_option | O_NONBLOCK; // 设置为非阻塞
fcntl(fd, F_SETFL, new_option);
return old_option;
}
int main(int argc, char* argv[])
{
//1.创建一个socket
int clientfd = socket(AF_INET, SOCK_STREAM, 0);
if (clientfd == -1)
{
std::cout << "create client socket error." << std::endl;
return -1;
}
//2.连接服务器
struct sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(SERVER_ADDRESS);
serveraddr.sin_port = htons(SERVER_PORT);
if (connect(clientfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) == -1)
{
std::cout << "connect socket error." << std::endl;
close(clientfd);
return -1;
}
//3. 不断向服务器发送数据,或者出错退出
int count = 0;
//setnonblocking(clientfd); // 将clientfd设置为非阻塞
while (true)
{
int ret = ::write(clientfd, SEND_DATA, strlen(SEND_DATA));
std::cout<<"ret:"<<ret<<std::endl;
if (ret != strlen(SEND_DATA))
{
std::cout << "send data error." << std::endl;
break;
}
else
{
count ++;
std::cout << "send data successfully, count = " << count << std::endl;
}
}
//5. 关闭socket
close(clientfd);
return 0;
}
最后当客户端的操作系统缓冲区内的数据满的时候,进行阻塞了;
满了之后阻塞,直到数据被recv
当对文件描述设置为非阻塞的时候,当缓冲区写完的时候,不会卡在wrtie处,会显示接下来的内容;
setnonblocking(clientfd); // 将clientfd设置为非阻塞
参考:
https://codeantenna.com/a/SdTXxsiy6g