我写了一个客户端,必须绑定客户端套接字。这很好。之后,我尝试连接Socket,并收到错误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()返回此错误
答案 0 :(得分:1)
我必须实现与多个服务器对话的客户端。服务器仅接受来自特定端口的消息,因此我必须绑定我的客户端套接字。
这是一个无法解决的问题。进行出站TCP连接时,本地IP地址和端口的组合专门为该特定的出站TCP连接保留。如果需要从同一端口建立多个出站TCP连接,则每个都必须绑定到其自己的本地IP地址。这将非常不便。
还有其他问题。假设您完成一个连接,然后尝试启动一个新的连接。新的将具有相同的本地IP地址,本地端口(因为服务器只能容忍一个),远程IP地址和远程端口。新连接的数据包如何与旧的旧数据包区分开?
这就是为什么在尝试connect
时收到错误消息的原因。直到知道连接的所有四个参数(本地和远程地址以及本地和远程端口)后,才能检测到与先前连接的冲突。直到您致电connect
为止,这一点是未知的。
您需要修复服务器以忽略源端口。如果绝对不能做到这一点,则必须采用等待重试机制来处理与过去连接的冲突。