C ++-bind()失败

时间:2019-06-11 11:35:36

标签: c++ sockets

我正在尝试使用C ++学习网络,并且试图建立一个简单的演示,在该示例中,我在端口5000上打开一个TCP服务器,然后立即将其关闭。这是我的代码:

#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>

int main()
{
    int port = 5000;
    std::cout << "Port: " << port << "\n";
    int socketdesc = socket(SOCK_STREAM, AF_INET, 0);

    if (socketdesc == 0)
    {
        std::cout << "Failed to create socket description.\n";
        return 1;
    }

    int opt = 1;

    if (setsockopt(socketdesc, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
               &opt, sizeof(opt)))
    {
        std::cout << "Failed to attach socket.\n";
        return 1;
    }

    struct sockaddr_in address;
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(port);

    if (bind(socketdesc, (struct sockaddr *)&address,
         sizeof(address)) < 0)
    {
        std::cout << "Failed to bind socket!\n";
        return 1;
    }

    std::cout << "Listening with protocol TCP on port" << port << ".\n";

    if (listen(socketdesc, 3) < 0)
    {
        std::cout << "Failed to listen!\n";
        return 1;
    }

    if (shutdown(socketdesc, SHUT_RDWR) < 0)
    {
        std::cout << "Failed to close socket!\n";
        return 1;
    }

    std::cout << "TCP test succeeeded.\n";
    return 0;
}

尝试将套接字绑定到端口5000时出现错误。设置TCP服务器端口出了什么问题?

P.S:opt位到底是什么(我正在关注一个教程,同时查看sys / socket的文档)?

2 个答案:

答案 0 :(得分:1)

在您到达bind()之前,您的代码中存在一些错误:

  

int socketdesc = socket(SOCK_STREAM,AF_INET,0);

您将前两个参数值向后移动,则调用应改为如下所示:

int socketdesc = socket(AF_INET, SOCK_STREAM, 0);
  

如果(socketdesc == 0)

socket()在错误时返回-1,而不是0。

  

如果(setsockopt(socketdesc,SOL_SOCKET,SO_REUSEADDR | SO_REUSEPORT,&opt,sizeof(opt)))

setsockopt()也会在错误时返回-1。

但更重要的是,您不能像这样在单个调用中组合多个套接字选项。您需要分别为每个选项调用setsockopt()

if (setsockopt(socketdesc, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
...

if (setsockopt(socketdesc, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)) < 0)
...

话虽如此,请尝试以下操作:

#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>

int main()
{
    int port = 5000;
    std::cout << "Port: " << port << "\n";

    int socketdesc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (socketdesc == -1)
    {
        std::cout << "Failed to create socket descriptor. " << strerror(errno) << "\n";
        return 1;
    }

    int opt = 1;

    if (setsockopt(socketdesc, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
    {
        std::cout << "Failed to set SO_REUSEADDR option. " << strerror(errno) << "\n";
        return 1;
    }

    if (setsockopt(socketdesc, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)) < 0)
    {
        std::cout << "Failed to set SO_REUSEPORT option. " << strerror(errno) << "\n";
        return 1;
    }

    struct sockaddr_in address;
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(port);

    if (bind(socketdesc, (struct sockaddr *)&address, sizeof(address)) < 0)
    {
        std::cout << "Failed to bind socket! " << strerror(errno) << "\n";
        return 1;
    }

    std::cout << "Listening with protocol TCP on port" << port << ".\n";

    if (listen(socketdesc, 3) < 0)
    {
        std::cout << "Failed to listen on socket! " << strerror(errno) << "\n";
        return 1;
    }

    if (shutdown(socketdesc, SHUT_RDWR) < 0)
    {
        std::cout << "Failed to close socket! " << strerror(errno) << "\n";
        return 1;
    }

    close(socketdesc);

    std::cout << "TCP test succeeeded.\n";
    return 0;
}

答案 1 :(得分:0)

即使现在不是这种情况,我将在此处保留此答案。我认为这仍然是一个真实的案例,有人在网站上寻找答案可能会对此表示赞赏。

(上面代码的真正答案是在注释中)


您需要关闭套接字,但尚未在每个故障状态下都关闭。即使过程结束,它也会保持打开状态并阻止您再次绑定它。

如果不是这种情况,则可能有其他程序在使用该端口。尝试更改端口号。