клиентский сокет является привязываемым, но не подключаемым, потому что уже используется - PullRequest
1 голос
/ 17 июня 2019

Я пишу клиента, где я должен связать клиентский сокет.Это отлично работает.После этого я пытаюсь подключить сокет и получаю ошибку 10048. (Адрес уже используется.) Я не понимаю, как это возможно.

Я должен реализовать клиент, говорящий с несколькими серверами.Каждый сервер принимает сообщения только от определенного порта.(каждый сервер ожидает свой порт).поэтому я должен связать свой клиентский сокет.Код выше для создания одного из этих сокетов.Мой код работает несколько раз.Но очень часто подключение дает мне ошибку 10048, в то время как привязка раньше была в порядке.Я знаю, что bind может также выдавать ошибку 10048, если сокет уже используется.Но это не так.Возвращает 0. Итак, я думаю, порт свободен.Сразу после привязки я вызываю connect и получаю ошибку 10048. Не понимаю почему?В момент привязки порт был явно свободен.

bool TEthernetSocket::Open()
{
    WSADATA wsaData;

    if (WSAStartup((MAKEWORD(2, 0)), &wsaData) == SOCKET_ERROR)
    {
       return IsConnected();
    }

    Socket = socket(AF_INET, SOCK_STREAM, 0); // TCP

    if (Socket == INVALID_SOCKET)
    {
        return false;
    }

    //bind Socket
    struct sockaddr_in sa_loc;
    memset(&sa_loc, 0, sizeof(struct sockaddr_in));
    sa_loc.sin_family = AF_INET;
    sa_loc.sin_port = htons(ClientPort);
    sa_loc.sin_addr.s_addr = inet_addr(IPClient.substr(0, 15).c_str());

    CALL_TRACE_CB("ethernetSocket connected");

    if (!(bind(Socket, (struct sockaddr*)&sa_loc, sizeof(struct  
    sockaddr))))
    {
        CALL_TRACE_CB("Bind works");
    }
    else
    {
        AnsiString msg = AnsiString().sprintf("EN: error socket Bind: 
        %d", WSAGetLastError());
        CALL_ERROR_CB(ERROR_NO_PORT_HANDLE, msg.c_str());
        Close();
    }


    // TCP
    SOCKADDR_IN sAdd;
    sAdd.sin_family = AF_INET;
    sAdd.sin_port = htons(Port);
    sAdd.sin_addr.s_addr = inet_addr(IP.substr(0, 15).c_str());

    if (connect(Socket, (SOCKADDR*)&sAdd, sizeof(SOCKADDR_IN)) ==    
    SOCKET_ERROR)
    {
        AnsiString msg = AnsiString().sprintf("EN: error connect        
        errorcode: %d", WSAGetLastError());
    }
}

Я ожидаю, что bind () вернет 10048, прежде чем connect вернет эту ошибку, но фактическое только connect () вернет эту ошибку

1 Ответ

1 голос
/ 17 июня 2019

Я должен реализовать клиент, говорящий с несколькими серверами.Сервер принимает сообщения только от определенного порта, поэтому я должен связать свой клиентский сокет.

Это неразрешимая проблема.Когда вы создаете исходящее TCP-соединение, комбинация локального IP-адреса и порта резервируется исключительно для этого конкретного исходящего TCP-соединения.Если вам нужно сделать несколько исходящих TCP-соединений с одного и того же порта, каждое из них должно быть привязано к своему локальному IP-адресу.Это будет крайне неудобно.

Есть и другие проблемы.Допустим, вы завершили одно соединение, а затем попробуйте установить новое.Новый будет иметь тот же локальный IP-адрес, локальный порт (поскольку сервер допускает только один), удаленный IP-адрес и удаленный порт.Как пакеты от нового соединения будут отличаться от старых, устаревших пакетов от старого?

Вот почему вы получаете сообщение об ошибке при попытке connect.Пока все четыре параметра соединения (локальный и удаленный адрес, а также локальный и удаленный порт) не станут известны, обнаруживается конфликт с предшествующим соединением.Это неизвестно, пока вы не позвоните connect.

. Вам нужно исправить сервер, чтобы он игнорировал порт источника.Если это абсолютно невозможно сделать, вам придется использовать механизм ожидания и повтора для обработки коллизий с прошлыми соединениями.

...