c++实现recv,send非堵塞
时间: 2024-01-17 21:30:21 浏览: 25
要实现非阻塞的recv和send操作,你可以使用套接字的非阻塞模式和非阻塞I/O函数。以下是使用C++实现的示例代码:
```cpp
#include <iostream>
#include <string>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
// 创建套接字
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
std::cerr << "Failed to create socket" << std::endl;
return 1;
}
// 设置套接字为非阻塞模式
int flags = fcntl(sockfd, F_GETFL, 0);
if (flags == -1) {
std::cerr << "Failed to get socket flags" << std::endl;
close(sockfd);
return 1;
}
if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) == -1) {
std::cerr << "Failed to set socket to non-blocking mode" << std::endl;
close(sockfd);
return 1;
}
// 发起连接
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(12345);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
if (connect(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == -1) {
if (errno != EINPROGRESS) {
std::cerr << "Failed to connect" << std::endl;
close(sockfd);
return 1;
}
}
// 发送数据
std::string message = "Hello, server!";
ssize_t bytesSent = send(sockfd, message.c_str(), message.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
if (bytesSent == -1) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
std::cerr << "Failed to send data" << std::endl;
close(sockfd);
return 1;
}
}
// 接收数据
char buffer[1024];
ssize_t bytesRead = recv(sockfd, buffer, sizeof(buffer), MSG_NOSIGNAL | MSG_DONTWAIT);
if (bytesRead == -1) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
std::cerr << "Failed to receive data" << std::endl;
close(sockfd);
return 1;
}
} else if (bytesRead == 0) {
std::cout << "Connection closed by peer" << std::endl;
close(sockfd);
return 0;
} else {
std::cout << "Received data: " << std::string(buffer, bytesRead) << std::endl;
}
// 关闭套接字
close(sockfd);
return 0;
}
```
在上述代码中,我们首先创建一个套接字,并将其设置为非阻塞模式。然后,我们使用非阻塞的`connect`函数进行连接,如果连接未立即建立,则会返回错误码`EINPROGRESS`。接下来,我们使用非阻塞的`send`函数发送数据,如果发送操作无法立即完成,则会返回错误码`EAGAIN`或`EWOULDBLOCK`。最后,我们使用非阻塞的`recv`函数接收数据,如果没有可用数据,则会返回错误码`EAGAIN`或`EWOULDBLOCK`。
请注意,非阻塞的recv和send操作可能需要在循环中多次尝试,直到操作完成或出现错误。此外,由于使用了非阻塞模式,你需要处理返回的错误码并在适当的时候进行重试。