【发布时间】:2021-07-17 20:58:06
【问题描述】:
我最近一直在学习 Unix 中的网络,并编写了这两个简单的程序,等待连接,接收消息,然后将相同的消息发送回发送者:
发送.cpp
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <iostream>
#include <unistd.h>
int main(int argc, char const *argv[])
{
struct addrinfo hints, *res;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
getaddrinfo(NULL, "2000", &hints, &res);
int sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (auto error = connect(sockfd, res->ai_addr, res->ai_addrlen) < 0){
std::cout << strerror(errno) << '\n';
exit(1);
}
char msg[] = "Hello, World";
send(sockfd, &msg, sizeof(msg), 0);
char input[sizeof(msg)];
recv(sockfd, &input, sizeof(input), 0);
std::cout << input << '\n';
close(sockfd);
return 0;
}
receive.cpp
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/poll.h>
#include <iostream>
#include <unistd.h>
int main(int argc, char const *argv[])
{
struct addrinfo hints, *res;
int sockfd, new_fd;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
getaddrinfo(NULL, "2000", &hints, &res);
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
bind(sockfd, res->ai_addr, res->ai_addrlen);
listen(sockfd, 5);
struct sockaddr_storage their_addr1;
socklen_t addr_size;
addr_size = sizeof(their_addr1);
new_fd = accept(sockfd, (struct sockaddr *)&their_addr1, &addr_size);
if (new_fd < 0)
{
std::cout << "Error" << '\n';
std::cout << strerror(errno) << '\n';
exit(1);
}
std::cout << "Accepted" << '\n';
char msg[255];
auto n = recv(new_fd, &msg, 255, 0);
std::cout << msg << '\n';
send(new_fd, &msg, n, 0);
close(sockfd);
close(new_fd);
return 0;
}
如果我运行receive.cpp,然后快速(在大约 5 秒内)运行send.cpp,(从命令行运行两者)程序运行良好,但如果我花费更长的时间,那么发送程序总是得到一个拒绝连接错误,接收程序永远不会终止。据我了解,accept() 调用会阻塞应用程序的其余部分并继续侦听,直到出现有效连接。这不是它的工作原理吗?任何帮助都会非常感谢您。
【问题讨论】:
-
您不应在
send.cpp中指定AI_PASSIVE,请参阅:man7.org/linux/man-pages/man3/getaddrinfo.3.html。也许就是这样。 -
即使我用机器本地 IP 地址替换它时,也会发生同样的行为,我使用 AI_PASSIVE 只是为了让它在我的两台机器上都可以工作,而无需修改代码
-
问题不是你想的那样。首先,检查
bind的返回值(与其他所有函数一样)。二、查SO_REUSEADDR和TIME_WAIT -
if (auto error = connect(...) < 0)不会将error设置为您的想法,因为<的优先级高于=。请改用int error; if ((error = connect(...)) < 0)。此外,您没有检查getaddrinfo()或bind()或listen()的返回值。send.cpp为getaddrinfo()使用的参数对于connect()是错误的。
标签: c++ networking unix-socket