winsock 无法连接到本地主机

winsock fails to connect to localhost

对于我的项目,我无法调试程序,所以我不能确定为什么会出现此错误。

我的托管在 c# 上的服务器无法连接到本地主机上的服务器。

它没有向我的服务器发回“连接”信号,而是永远连接不上,我认为代码写得很好,我看不到任何错误,也许我在某处犯了一个粗心的错误

此外,我必须使用 gethostbyname 而不是 getaddrinfo

winsock 命名空间:

SOCKET WinSock::ConnectToServer(PCHAR IP, USHORT Port)
{
    WSADATA WSA;
    if (WSAStartup(MAKEWORD(2, 0), &WSA))
    {
        SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (s != SOCKET_ERROR)
        {
            hostent *Host = gethostbyname(IP);
            if (Host != ERROR)
            {
                SOCKADDR_IN Addr;

                Addr.sin_family = AF_INET;
                Addr.sin_port = htons(Port);
                Addr.sin_addr.s_addr = NULL;

                if (bind(s, PSOCKADDR(&Addr), sizeof(Addr)) > 0)
                {
                    return s;
                }
            }
        }
    }

    return FALSE;
}

BOOL WinSock::SendData(SOCKET s, PBYTE Packet)
{
    DWORD PacketSize = lstrlenA(PCHAR(Packet));
    if (send(s, PCHAR(&PacketSize), 8, 0) > NULL)
    {
        if (send(s, PCHAR(Packet), PacketSize, 0) > NULL)
        {
            return TRUE;
        }
    }
    return FALSE;
}

主要方法:

int main()
{
    char key = 1;
    SOCKET S = WinSock::ConnectToServer(0, 55480);
    while(true)
    {
        WinSock:SendData(S, (PBYTE)key);
    }
}
            if (bind(s, PSOCKADDR(&Addr), sizeof(Addr)) > 0)

这段代码的描述是它应该连接到服务器。但问题是 bind() 没有连接到任何服务器。它只将套接字链接到本地​​端口。这就是侦听套接字的服务器所做的。这大概是服务器已经打开的同一个端口,因此 bind() 失败。如果服务器没有监听,bind() 将会成功,具有讽刺意味的是。但无论如何,它不会连接到任何东西。

您想使用 connect() 而不是 bind()

此外,我必须注意,如果此函数首先创建了一个套接字,但随后由于此原因或任何其他原因无法建立连接,它将 return 一个错误指示但无法关闭套接字,从而泄漏套接字描述符。你也必须修复这个错误。

您实际上并没有与服务器建立连接。您正在调用 bind() 将客户端套接字绑定到 local 端口 55480,但这不会创建连接。您需要改为调用 connect() 将客户端套接字连接到 远程 端口 55480。

此外,您的 SendData() 编码错误。它告诉 send()PacketSize 发送 8 个字节,但是 DWORD 的大小只有 4 个字节。并且 send() 不会 return NULL 失败。并且 send() 不保证发送所有请求的字节,所以你需要在循环中调用它。并且习惯上以网络字节顺序(big endian)发送多字节整数。

此外,您已将 SendData() 编码为期望以 null 结尾的 C 样式字符串,但这并不是您的 main() 实际传递给它的内容。

试试像这样的东西:

bool WinSock::Init()
{
    WSADATA WSA;
    return (WSAStartup(MAKEWORD(2, 0), &WSA) == 0);
}

bool WinSock::Cleanup()
{
    return (WSACleanup() == 0);
}

SOCKET WinSock::ConnectToServer(const char *IP, unsigned short Port)
{
    hostent *Host = gethostbyname(IP);
    if ((Host != NULL) && (Host->h_addrtype == AF_INET)
    {
        SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (s != INVALID_SOCKET)
        {
            SOCKADDR_IN Addr = {};

            Addr.sin_family = AF_INET;
            Addr.sin_port = htons(Port);
            Addr.sin_addr.s_addr = * (u_long*) Host->h_addr;

            if (connect(s, PSOCKADDR(&Addr), sizeof(Addr)) != SOCKET_ERROR)
            {
                return s;
            }

            closesocket(s);
        }
    }

    return INVALID_SOCKET;
}

bool WinSock::Close(SOCKET s)
{
    return (closesocket(s) == 0);
}

bool WinSock::SendData(SOCKET s, const void* Data, DWORD DataSize)
{
    const char *ptr = (const char*) Data;

    while (DataSize > 0)
    {
        int numSent = send(s, ptr, DataSize, 0);
        if (numSent == SOCKET_ERROR) return false;
        ptr += numSent;
        DataSize -= numSent;
    }

    return true;
}

bool WinSock::SendData(SOCKET s, const char *Packet)
{
    DWORD PacketSize = lstrlenA(Packet);
    DWORD tmp = htonl(PacketSize);
    if (!SendData(s, &tmp, sizeof(tmp)) return false;
    return SendData(s, Packet, PacketSize);
}
int main()
{
    if (WinSock::Init())
    {
        const char *key = "1";
        SOCKET S = WinSock::ConnectToServer(NULL, 55480);
        if (s != INVALID_SOCKET)
        {
            while (true)
            {
                WinSock:SendData(S, key);
            }
            WinSock::Close(s);
        }
        WinSock::Cleanup();
    }

    return 0;
}