简体   繁体   English

客户端套接字可绑定但不可连接,因为已在使用

[英]client socket is bindable but not connectable, because already in use

I write a client, where i have to bind the client socket.我写了一个客户端,我必须在其中绑定客户端套接字。 This works fine.这工作正常。 After that i try to connect the Socket and i get error 10048. (Address already in use.) I don't understand how this is possible.之后,我尝试连接 Socket,但出现错误 10048。(地址已在使用中。)我不明白这是怎么可能的。

I have to implement a client speaking with multiple server.我必须实现一个与多个服务器对话的客户端。 Every server only accepts messages from a specific port.每个服务器只接受来自特定端口的消息。 (every Server expects a different port). (每个服务器都需要不同的端口)。 so i have to bind my client socket.所以我必须绑定我的客户端套接字。 The code above is to create one of these sockets.上面的代码是创建这些套接字之一。 My code works some times.我的代码有时会起作用。 But very often the connect gives me the error 10048, while the binding before was fine.但是连接经常给我错误 10048,而之前的绑定很好。 I know that bind can give also the error 10048 if the socket is already in use.我知道如果套接字已经在使用中,bind 也会给出错误 10048。 But it doesn't.但事实并非如此。 It returns 0. So i guess the port is free.它返回 0。所以我猜端口是免费的。 Immediate after binding i call connect and get error 10048. I do not understand why?绑定后立即调用 connect 并收到错误 10048。我不明白为什么? At the moment of the binding the port was obviously free.在绑定的那一刻,端口显然是空闲的。

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());
    }
}

I expect that bind() returns 10048 before connect returns this error, but actual only connect() returns this error我希望 bind() 在 connect 返回此错误之前返回 10048,但实际上只有 connect() 返回此错误

I have to implement a client speaking with multiple server.我必须实现一个与多个服务器对话的客户端。 The server only accepts messages from a specific port, so i have to bind my client socket.服务器只接受来自特定端口的消息,所以我必须绑定我的客户端套接字。

This is an unsolvable problem.这是一个无法解决的问题。 When you make an outbound TCP connection, the combination of local IP address and port is reserved exclusively for that particular outbound TCP connection.当您建立出站 TCP 连接时,本地 IP 地址和端口的组合专为该特定出站 TCP 连接保留。 If you need to make multiple outbound TCP connections from the same port, each will have to be bound to its own local IP address.如果您需要从同一个端口建立多个出站 TCP 连接,每个连接都必须绑定到自己的本地 IP 地址。 That is going to be extremely inconvenient.这将是非常不方便的。

There are other problems too.还有其他问题。 Say you finish one connection and then try to start a new one.假设您完成了一个连接,然后尝试开始一个新的连接。 The new one will have the same local IP address, local port (since the server only tolerates one), remote IP address, and remote port.新的将具有相同的本地 IP 地址、本地端口(因为服务器只允许一个)、远程 IP 地址和远程端口。 How will packets from the new connection be distinguished from old, stale packets from the old one?如何区分来自新连接的数据包和来自旧连接的旧数据包?

This is why you get the error when you try to connect .这就是您在尝试connect时收到错误的原因。 It's not until all four parameters of the connection (local and remote address and local and remote port) are known that the collision with the prior connection is detectable.直到知道连接的所有四个参数(本地和远程地址以及本地和远程端口),才能检测到与先前连接的冲突。 That's not known until you call connect .在您调用connect之前,这是未知的。

You need to fix the server to ignore the source port.您需要修复服务器以忽略源端口。 If that absolutely cannot be done, you'll have to adopt a wait and retry mechanism to handle collisions with past connections.如果这绝对不能完成,您将不得不采用等待和重试机制来处理与过去连接的冲突。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM