【问题标题】:bind returns address in use even if no connection is established即使没有建立连接,bind 也会返回正在使用的地址
【发布时间】:2014-06-30 10:48:35
【问题描述】:

我有一个 C++ 代码,我试图在其中建立一个套接字上的连接。但我首先需要检查给定端口上是否已经存在连接,如果存在,我需要关闭连接。我有下面的代码,我的问题是,当检查端口是否已经连接时,即使之前连接失败,它也会返回。

connected = false;
int sockfd;
void conn(int port) {
   struct sockaddr_in addr;
   addr.sin_family = AF_INET;
   addr.sin_port   = htons(port);
   .....
   int sockfd_t;
   if ( (sockfd_t = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
       cout << "Error opening socket_test " << endl;
       return;
   }
   // check if address already in use
   if (bind(sockfd_t, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
        if(errno == EADDRINUSE) {
        cout << "address in use: bind fail, port=" << port << endl;
    }
        // do something - close the connection if already connected
    }
    else {
        cout << "bind ok, port=" << port << endl;
    }
    close(sockfd_t);

    if ( (sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
       cout << "Error opening socket " << endl;
       return;
    }

    if (connect(sockfd, (struct sockaddr *) &adresse, sizeof(adresse))) {
        cout << "Error connecting" << endl;
        close(sockfd);
        return;
    }

    connected = true;
}

int main() {
    int port=3590;
    while (!connected) {
       conn(port);
    }
    cout << "CONNECTED";
    // ..........
}

运行程序后,输出如下:

bind ok, port=3590;
Error connecting
bind ok, port=3590;
Error connecting
address in use: bind fail, port=3590 //???
CONNECTED!

我不知道为什么在打印的第 5 行显示“正在使用的地址:...”,因为前两次连接失败?

【问题讨论】:

  • 你在使用 SO_REUSADDR 吗?

标签: c++ sockets


【解决方案1】:

我认为您对这些套接字操作的作用有误解。

但我首先需要检查给定端口上是否已经存在连接,如果存在我需要关闭连接。

  1. bind() 为套接字提供一个本地地址,而不是检查您尝试连接的远程地址是否可访问。

    李>
  2. connect() 将套接字连接到远程地址

  3. 当连接一个套接字作为客户端时(这是我认为你正在尝试做的),你不需要检查是否已经有连接,远程服务器可以处理多个传入的客户端连接到同一个端口。绑定通常只对服务器很重要。

  4. 如果连接前不绑定,socket会被随机分配一个本地端口。

所以,如果您是客户,您可以这样做:

  1. socket()
  2. connect()

如果您是服务器,您可以:

  1. socket()
  2. bind()
  3. listen()

在您自己的问题中,当没有服务器侦听时,输出才有意义,但随后有服务器上线。

  1. 前两次,你绑定了一个socket,它成功了,因为没有人用它来监听,然后你连接失败,因为你刚刚绑定,并没有启动服务器(通过调用listen()) .

  2. 然后同一主机上的真实服务器绑定该套接字并开始侦听,因此您无法再绑定该端口(失败),但您可以连接,因为服务器正在侦听。

【讨论】:

  • 客户端可以在调用connect() 之前bind() 到特定的本地IP/端口。一些协议要求这样做。如果未事先调用 bind()connect() 在内部执行隐式 bind()。此外,调用bind() 的简单操作将在套接字关闭后锁定本地IP/端口一段时间以供使用。这也可以解释为什么会出现EADDRINUSE 错误。
猜你喜欢
  • 2018-04-14
  • 2013-10-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-12
  • 2018-05-13
  • 2020-12-10
  • 2013-01-19
  • 2021-10-22
相关资源
最近更新 更多