Windows – ConnectEx要求套接字“最初绑定”,但是要什么?
ConnectEx功能需要“未连接的,先前绑定的套接字”.实际上,如果我省略了我的示例中的
bind步骤(见下文),则
ConnectEx在
WSAEINVAL失败.
这是我目前的理解:在调用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不会. 我的问题是: >我的评估是否正确? 使用ConnectEx示例(也在Gist:https://gist.github.com/4158972上): #include <stdio.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: %dn",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: %dn",WSAGetLastError()); return 1; } sock = socket(AF_INET,0); if (sock == INVALID_SOCKET) { printf("socket: %dn",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: %dn",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 immediatelyn"); } else if (WSAGetLastError() == ERROR_IO_PENDING) { printf("ConnectEx pendingn"); DWORD numBytes; ok = GetOverlappedResult((HANDLE) sock,&ol,&numBytes,TRUE); if (ok) printf("ConnectEx succeededn"); else printf("ConnectEx failed: %dn",WSAGetLastError()); } else { printf("ConnectEx failed: %dn",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: %dn",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: %dn",WSAGetLastError()); return 1; } printf("Donen"); return 0; }
正确.
是.
我相信INADDR_ANY在所有地址族中都是一堆零,所以你可以尝试使用memset()并完全省略addr.sin_addr.s_addr的赋值.这是否是犹太人,便携式,政治上正确等等,是我不会进入的另一个问题. 似乎很奇怪微软没有设法让ConnectEx()在内部调用bind(),考虑到保存系统调用是其存在的动机,并且还考虑到大多数程序根本不会绑定出站套接字. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 在Windows 8和Windows Phone 8上使用带有HTML5 / Javascrip
- 超高速多进程操作key为uint32 value为uint32的数据(用于监
- winapi – 在MS Windows(XP)上使用来自不同进程的窗口句柄进
- Skype URI无法在iOS 9中运行
- windows-10 – WAMP服务器在Windows 10上无法正常运行
- window2016 域重命名
- 在Windows 7中捕获控制台退出C#
- windows-services – 文件系统上的哪个位置Windows服务应该
- windows – 使用Delphi 7中的WMI进行内存泄漏
- Windows – DNS服务器配置问题,PTR记录
- active-directory – Windows 2008 R2上的FreeNA
- windows – 设置EXE VersionInfo
- windows-phone-7 – 如何将SqlCe数据库部署到用于
- windows – Combobox更改高亮颜色winRT(metro应用
- windows – CMake / CPack可以为单个项目生成多个
- .Net DateTime到DOS日期32位转换
- 在Windows和Linux上获取Python中唯一的计算机ID
- Windows Python:为什么第一个打开的窗口未显示为
- 从Windows 10 Universal App中的MainPage打开一个
- SecureCRT的快捷键