wordpress   发布时间:2022-04-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了Windows – ConnectEx要求套接字“最初绑定”,但是要什么?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

概述

ConnectEx功能需要“未连接的,先前绑定的套接字”.实际上,如果我省略了我的示例中的 bind步骤(见下文),则 ConnectEx在 WSAEINVAL失败. 这是我目前的理解:在调用ConnectEx之前,bind将套接字调用到INADDR_ANY和端口0(除非它已被绑定): struct sockaddr_in addr; ZeroMemory(&addr, sizeof(addr))
ConnectEx功能需要“未连接的,先前绑定的套接字”.实际上,如果我省略了我的示例中的 bind步骤(见下文),则 ConnectExWSAEINVAL失败.

这是我目前的理解:在调用ConnectEx之前,bind套接调用到INADDR_ANY和端口0(除非它已被绑定):

struct sockaddr_in addr;
ZeroMemory(&addr,sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = 0;
rc = bind(sock,(SOCKADDR*) &addr,sizeof(addr));
if (rc != 0) { ... bind Failed; call WSAGetLastError to see why ... }

或者对于IPv6套接字:

struct sockaddr_in6 addr;
ZeroMemory(&addr,sizeof(addr));
addr.sin6_family = AF_INET6;
addr.sin6_addr = in6addr_any;
addr.sin6_port = 0;
rc = bind(sock,sizeof(addr));
if (rc != 0) { ... bind Failed; call WSAGetLastError to see why ... }

这允许操作系统为我们的套接字分配本地地址(而不是我们连接的远程地址). connect自动执行此步骤,但ConnectEx不会.

我的问题是:

>我的评估是否正确?
>有没有办法对地址族进行无关的自动绑定,还是我必须手动处理AF_INET,AF_INET6,AF_BTH(蓝牙)等各个?

使用COnnectEx示例(也在Gist:https://gist.github.com/4158972上):

#include <st@L_874_20@.h>
#include <WinSock2.h>
#include <MSWSock.h>
#include <WS2tcpip.h>

#pragma comment(lib,"Ws2_32.lib")

struct mswsock_s {
    LPFN_CONNECTEX ConnectEx;
} mswsock;

static BOOL load_mswsock(void)
{
    SOCKET sock;
    DWORD dwBytes;
    int rc;

    /* Dummy socket needed for WSAIoctl */
    sock = socket(AF_INET,SOCK_STREAM,0);
    if (sock == INVALID_SOCKET)
        return falSE;

    {
        GUID guid = WSAID_CONNECTEX;
        rc = WSAIoctl(sock,SIO_GET_EXTENSION_FUNCTION_POINTER,&guid,sizeof(guid),&mswsock.ConnectEx,sizeof(mswsock.ConnectEX),&dwBytes,NULL,null);
        if (rc != 0)
            return falSE;
    }

    rc = closesocket(sock);
    if (rc != 0)
        return falSE;

    return TRUE;
}

int main(int argc,char *argv[])
{
    int rc;
    BOOL ok;
    WSADATA wsaData;
    SOCKET sock;

    rc = WSAStartup(MAKEWORD(2,2),&wsaData);
    if (rc != 0) {
        printf("WSAStartup Failed: %d\n",rc);
        return 1;
    }
    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
        printf("Your computer is from the wrong millenium.\n");
        WSACleanup();
        return 1;
    }

    if (!load_mswsock()) {
        printf("Error loading mswsock functions: %d\n",WSAGetLastError());
        return 1;
    }

    sock = socket(AF_INET,0);
    if (sock == INVALID_SOCKET) {
        printf("socket: %d\n",WSAGetLastError());
        return 1;
    }

    /* ConnectEx requires the socket to be initially bound. */
    {
        struct sockaddr_in addr;
        ZeroMemory(&addr,sizeof(addr));
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = INADDR_ANY;
        addr.sin_port = 0;
        rc = bind(sock,sizeof(addr));
        if (rc != 0) {
            printf("bind Failed: %d\n",WSAGetLastError());
            return 1;
        }
    }

    /* Issue ConnectEx and wait for the operation to complete. */
    {
        OVERLAPPED ol;
        ZeroMemory(&ol,sizeof(ol));

        sockaddr_in addr;
        ZeroMemory(&addr,sizeof(addr));
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = inet_addr("173.194.37.36"); // google.com
        addr.sin_port = htons(80);

        ok = mswsock.ConnectEx(sock,sizeof(addr),&ol);
        if (ok) {
            printf("ConnectEx succeeded immediately\n");
        } else if (WSAGetLastError() == ERROR_IO_PENDING) {
            printf("ConnectEx pending\n");

            DWORD numbytes;
            ok = GetOverlappedResult((HANDLE) sock,&ol,&numbytes,TRUE);
            if (ok)
                printf("ConnectEx succeeded\n");
            else
                printf("ConnectEx Failed: %d\n",WSAGetLastError());
        } else {
            printf("ConnectEx Failed: %d\n",WSAGetLastError());
            return 1;
        }
    }

    /* Make the socket more well-behaved. */
    rc = setsockopt(sock,SOL_SOCKET,SO_updatE_CONNECT_COntexT,0);
    if (rc != 0) {
        printf("SO_updatE_CONNECT_COntexT Failed: %d\n",WSAGetLastError());
        return 1;
    }

    /* This will fail if SO_updatE_CONNECT_COntexT was not performed. */
    rc = shutdown(sock,SD_BOTH);
    if (rc != 0) {
        printf("shutdown Failed: %d\n",WSAGetLastError());
        return 1;
    }

    printf("Done\n");
    return 0;
}

正确.

是.

我相信INADDR_ANY在所有地址族中都是一堆零,所以你可以尝试使用memset()并完全省略addr.sin_addr.s_addr的赋值.这是否是犹太人,便携式,政治上正确等等,是我不会进入的另一个问题.

似乎很奇怪微软没有设法让ConnectEx()在内部调用bind(),虑到保存系统调用是其存在的动机,并且还虑到大多数程序根本不会绑定出站套接字.

大佬总结

以上是大佬教程为你收集整理的Windows – ConnectEx要求套接字“最初绑定”,但是要什么?全部内容,希望文章能够帮你解决Windows – ConnectEx要求套接字“最初绑定”,但是要什么?所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。