【问题标题】:Socket listen doesn't unbind in C++ under linuxlinux下的C++中socket监听不会解除绑定
【发布时间】:2011-01-13 14:16:11
【问题描述】:

我有一个侦听某个端口的套接字。 我将 SIGSTOP 信号发送到在端口上等待的线程(使用接受)并终止它。然后我关闭我等待的套接字的 fd。但是对于我的项目的下一次运行,它不允许我再次在该端口上监听。 我的程序是linux下的C++。 我该怎么办?

我的代码的某些部分是: 线程 1:

void* accepter(void *portNo) {
int newsockfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
}
struct sockaddr_in server;
bzero((char *) & server, sizeof (server));
server.sin_family = AF_INET;
server.sin_port = htons(*(int*) portNo);
server.sin_addr.s_addr = INADDR_ANY;
if (bind(sockfd, (struct sockaddr *) & server, sizeof (struct sockaddr_in)) < 0) {
perror("ERROR on binding");
}

listen(sockfd, 50);
while (true) {
struct sockaddr_in client;
socklen_t clientLen = sizeof (struct sockaddr_in);
newsockfd = accept(sockfd, (struct sockaddr *) & client, &clientLen);
if (accepterFlag) {
    break;
}
if (getpeername(newsockfd, (sockaddr *) & client, &clientLen) == -1) {
    perror("getpeername() failed");
}
sem_wait(setSem);
FD_SET(newsockfd, &set);
if (maxFd < newsockfd) {
    maxFd = newsockfd;
}
sem_post(setSem);
}

线程 2:

listenerFlag = true;
accepterFlag = true;
sleep(1);
pthread_kill(listenerThread, SIGSTOP);
pthread_kill(accepterThread, SIGSTOP);
close(sockfd);
sem_wait(setSem);
for (int i = 1; i <= maxFd; i++) {
if (FD_ISSET(i, &set)) {
    close(i);
}
}
sem_post(setSem);

谢谢。

【问题讨论】:

  • 也许尝试在接受线程终止时关闭套接字的 fd?
  • 您确定要发送SIGSTOP吗?以后有人要发SIGCONT吗?只要某些(停止的)线程仍在该套接字上的 accept 调用中,如果最终无法关闭套接字,我不会感到惊讶。 (你说你也终止了线程,我只是没有看到。)

标签: c++ linux sockets


【解决方案1】:

您是否知道,在您侦听完套接字后,套接字通常会被搁置一两分钟,以防止用于前一个进程的通信进入您的进程?它被称为“TIME_WAIT”状态。

如果您想覆盖该行为,请使用setsockopt 在侦听套接字之前针对套接字设置 SO_REUSEADDR 标志。

【讨论】:

  • 我在 Java 中就知道这一点。 C++也一样吗?
  • 是的,它是 TCP 的东西,而不是语言的东西,所以它适用于任何地方。
  • 对于存档,您似乎还需要在 Apple 上设置 SO_REUSEPORT 标志:int reusePort = 1; setsockopt(socket_, SOL_SOCKET, SO_REUSEPORT, &amp;reusePort, sizeof(reusePort));
【解决方案2】:

【讨论】:

  • 我知道。但它应该关闭。我怎样才能真正关闭它?
【解决方案3】:

我认为问题在于您没有正确关闭套接字和/或程序。套接字可能仍然存在于操作系统中。使用类似nesat -an 的东西检查它。您还应该检查您的进程是否已退出。如果它已经正确结束,它应该已经关闭了你的套接字。

你应该做的是:

  • 用信号中断你的线程。
  • 当你的线程被中断时,应该在结束前彻底关闭套接字。
  • 那么您就可以彻底退出程序了。

my2cents,

【讨论】:

  • 好的。那么 SO_REUSEADDR 是关键:-)
猜你喜欢
  • 2019-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-15
相关资源
最近更新 更多