【问题标题】:Connect method in winsock2 does not seem to workwinsock2 中的连接方法似乎不起作用
【发布时间】:2021-02-14 03:33:09
【问题描述】:
#define PORT 3000

int sock()
{
    int valread;
    struct sockaddr_in serv_addr;
    const char* hello = "Hello from client";
    char buffer[1024] = { 0 };
    SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0)
    {
        printf("\n Socket creation error \n");
        return -1;
    }

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);

    // Convert IPv4 and IPv6 addresses from text to binary form 
    if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0)
    {
        printf("\nInvalid address/ Address not supported \n");
        return -1;
    }

    if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
    {
        printf("\nConnection Failed \n");
        return -1;
    }
    send(sock, hello, strlen(hello), 0);
    printf("Hello message sent\n");

    return 0;
}

我有这个套接字代码,要在 localhost:3000 地址发送。但是它们没有发送,并且弹出连接失败错误。我在该端口打开了 node.js 服务器侦听器套接字。

【问题讨论】:

  • 错误是什么?使用perror获取相关信息。
  • @G.M.错误代码是 10093 它说“应用程序没有调用 WSAStartup,或者 WSAStartup 失败。”我不知道这意味着什么,虽然 xD 我使用了 GetLastError,因为我使用的是 Windows 10
  • 你给WSAStartup打过电话吗?如果是,通话是否成功?抱歉,错误信息似乎很清楚。

标签: c++ sockets


【解决方案1】:

仅在 Windows 1 上,您必须调用 WSAStartup() 来初始化 Winsock 库之前使用任何其他套接字函数,如 connect()。见Initializing Winsock。使用完 Winsock 后,您应该致电 WSACleanup()

1:在非Windows平台上,使用套接字时没有等效的启动/清理函数需要调用。

试试这样的:

#include <winsock2.h>
#include <windows.h>
#include <stdio.h>

#define PORT 3000

int main()
{
    WSADATA wsa;
    int iResult = WSAStartup(MAKEWORD(2,0), &wsa);
    if (iResult != 0)
    {
        printf("WSAStartup failed: %d\n", iResult);
        return INVALID_SOCKET;
    }

    printf("Winsock initialized\n");

    struct sockaddr_in serv_addr;
    ZeroMemory(&serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);

    // Convert IPv4 and IPv6 addresses from text to binary form 
    if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0)
    {
        printf("Invalid address/ Address not supported \n");
        WSACleanup();
        return -1;
    }

    SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock == INVALID_SOCKET)
    {
        printf("Socket creation failed: %d\n", WSAGetLastError());
        WSACleanup();
        return -1;
    }

    if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == SOCKET_ERROR)
    {
        printf("Connection failed: %d\n", WSAGetLastError());
        closesocket(sock);
        WSACleanup();
        return -1;
    }

    printf("Connection successful\n");

    const char* hello = "Hello from client";

    if (send(sock, hello, strlen(hello), 0) == SOCKET_ERROR)
    {
        printf("Send failed: %d\n", WSAGetLastError());
        closesocket(sock);
        WSACleanup();
        return -1;
    }

    printf("Hello message sent\n");

    closesocket(sock);
    WSACleanup();

    return 0;
}

也就是说,您确实应该使用getaddrinfo() 而不是inet_pton(),尤其是如果您想同时支持 IPv4 和 IPv6,例如:

#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <stdio.h>

#define PORT "3000"

int main()
{
    WSADATA wsa;
    int iResult = WSAStartup(MAKEWORD(2,0), &wsa);
    if (iResult != 0)
    {
        printf("WSAStartup failed: %d\n", iResult);
        return INVALID_SOCKET;
    }

    printf("Winsock initialized\n");

    struct addrinfo hints, *addrs;
    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    // Convert IPv4 and IPv6 addresses from text to binary form 
    iResult = getaddrinfo("127.0.0.1", PORT, &hints, &addrs);
    if (iResult != 0)
    {
        printf("Get Address Info failed: (%d) %s\n", iResult, gai_strerror(iResult));
        WSACleanup();
        return -1;
    }

    SOCKET sock = INVALID_SOCKET;

    for(struct addrinfo *addr = addrs; addr != NULL; addr = addr->ai_next)
    {
        sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
        if (sock != INVALID_SOCKET)
        {
            if (connect(sock, addr->ai_addr, addr->ai_addrlen) != SOCKET_ERROR)
                break;

            closesocket(sock);
            sock = INVALID_SOCKET;
        }
    }

    if (sock == INVALID_SOCKET)
    {
        printf("Socket creation failed/Connection failed\n");
        WSACleanup();
        return -1;
    }

    printf("Connection successful\n");

    const char* hello = "Hello from client";

    if (send(sock, hello, strlen(hello), 0) == SOCKET_ERROR)
    {
        printf("Send failed: %d\n", WSAGetLastError());
        closesocket(sock);
        WSACleanup();
        return -1;
    }

    printf("Hello message sent\n");

    closesocket(sock);
    WSACleanup();

    return 0;
}

【讨论】:

  • 好像发送了?但是在 node.js 和 wireshark 上没有回复 - prnt.sc/ze160d
  • @ddd 你的node.js 服务器期望你发送什么?您不能只向它发送任意数据,除非它充当回显服务器。否则,你必须发送它想要的东西。例如,如果它充当 Web 服务器,您必须向它发送有效的 HTTP 请求。你怎么知道它没有响应?在send() 完成后,此代码不会尝试读取任何响应。至于 Wireshark,如果没有additional setup,它就无法捕获 localhost 流量。
  • @ddd 您不能将(PCSTR)3000getaddrinfo() 一起使用,它需要真正的以空字符结尾的字符串,因此您必须改用"3000",就像我在示例中展示的那样
  • Node.js代码-pastebin.com/kapan7RZ使用“3000”后显示:Winsock初始化连接成功Hello消息发送
  • @ddd 我在您的服务器日志中没有看到"new connection" 消息。您确定您的客户端实际上是连接到您的 node.js 服务器而不是其他东西吗?使用netstat 进行验证。我不熟悉 node.js,但 io.on("connection", ...) 不应该是 before io.listen(),每个 documentation?此外,接受的 socket 正在等待几个事件,但我没有看到您的客户端发送任何与这些事件匹配的内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-25
  • 1970-01-01
  • 2023-02-04
  • 1970-01-01
  • 2021-11-27
  • 2021-09-13
  • 1970-01-01
相关资源
最近更新 更多