在windows上使用套接字以外的其他对象进行选择
在套接字+管道上执行select()调用时,我遇到了一个问题 我知道已经有一些关于这方面的话题了,但是我读了很多东西和它们的反面,我不知道什么是解决我问题的最佳方法 对我来说最好的方法是使用WaitForMultipleObjects()侦听这两个对象,但是当我尝试仅在WSAEvent对象上调用它时,它失败了,最后一个错误捕获是代码6(无效句柄) 因此WaitForMultipleObjects似乎不适用于WinSocks事件,但是我已经在网上看到了一些使用它的示例。 WSACreateEvent文档()的第二部分说: Windows Sockets 2事件对象是Windows中的系统对象 环境。因此,如果Windows应用程序希望使用 自动重置事件而不是手动重置事件,应用程序可以 直接调用CreateEvent函数 这并不意味着WSAEvent基于常规windows事件?如果是这样,为什么它不能与WaitForMultipleObjects一起工作?医生说它可以处理常规事件在windows上使用套接字以外的其他对象进行选择,windows,Windows,在套接字+管道上执行select()调用时,我遇到了一个问题 我知道已经有一些关于这方面的话题了,但是我读了很多东西和它们的反面,我不知道什么是解决我问题的最佳方法 对我来说最好的方法是使用WaitForMultipleObjects()侦听这两个对象,但是当我尝试仅在WSAEvent对象上调用它时,它失败了,最后一个错误捕获是代码6(无效句柄) 因此WaitForMultipleObjects似乎不适用于WinSocks事件,但是我已经在网上看到了一些使用它的示例。 WSACreateEven
感谢您的帮助。查看
WSAEVENT
的声明,发现WSAEVENT
只是HANDLE
的别名。这解释了您在帖子中添加的WSACreateEvent
文档的注释。因此,WSACreateEvent
通过调用CreateEvent(…,TRUE,FALSE,…)简单地创建一个手动重置事件代码>
因此,WSACreateEvent
返回的事件必须与WaitForMultipleObjects(…)
一起工作
根据您发布的代码,我看不出WaitForMultipleObjects(..)
在提供由WSACreateEvent
返回的事件时应返回“无效句柄”的任何原因
但管道可能不适用于WaitForMultipleObjects(..)
。我记得很久以前在这方面有问题,但现在我记不起细节了。但也许这是另一个开始挖掘的地方
下面是我的小测试应用程序的代码,它创建了两个线程(一个事件线程发送正常事件,一个简单的TCP/IP服务器发送数据)。在主循环中,建立与服务器的连接,并处理信号事件
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#pragma comment(lib, "Ws2_32.lib");
#define SERVER_PORT 5000
HANDLE hSomeEvent;
HANDLE hSocketEvent;
DWORD WINAPI eventThread(LPVOID pData)
{
while (1)
{
SleepEx(2250, FALSE);
SetEvent(hSomeEvent);
}
return (0);
}
DWORD WINAPI serverThread(LPVOID pData)
{
SOCKET listener;
struct sockaddr_in sockaddr;
int size;
SOCKET client;
listener = socket(AF_INET, SOCK_STREAM, 0);
if (listener == INVALID_SOCKET)
{
printf("Could not create socket : %d" , WSAGetLastError());
}
sockaddr.sin_family = AF_INET;
sockaddr.sin_addr.s_addr = INADDR_ANY;
sockaddr.sin_port = htons(SERVER_PORT);
if (bind(listener, (struct sockaddr *)&sockaddr , sizeof(sockaddr)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d" , WSAGetLastError());
}
listen(listener, 1);
while (listener)
{
size = sizeof(struct sockaddr_in);
client = accept(listener, (struct sockaddr *)&sockaddr, &size);
printf("client connected\n");
while (client != INVALID_SOCKET)
{
SleepEx(5000, FALSE);
if (send(client, "hello\0", 6, 0) != 6)
{
closesocket(client);
shutdown(client, 2);
client = INVALID_SOCKET;
}
}
SetEvent(hSomeEvent);
}
return (0);
}
int main()
{
WSADATA wsaData;
HANDLE events[2];
DWORD result;
SOCKET s;
struct hostent *hp;
struct sockaddr_in sockaddr;
int len;
char buff[1024 * 16];
HANDLE *evtPtr;
WSAStartup(MAKEWORD(2, 2), &wsaData);
hSocketEvent = WSACreateEvent();
//hSocketEvent = CreateEvent(NULL, FALSE, FALSE, "socket_event");
hSomeEvent = CreateEvent(NULL, FALSE, FALSE, "some_event");
CreateThread(NULL, 0, eventThread, NULL, 0, &result);
CreateThread(NULL, 0, serverThread, NULL, 0, &result);
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == INVALID_SOCKET)
{
printf("Could not create socket : %d" , WSAGetLastError());
}
hp = gethostbyname("127.0.0.1");
sockaddr.sin_addr.s_addr = *((unsigned long*)hp->h_addr);
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(SERVER_PORT);
if (connect(s, (struct sockaddr*)&sockaddr, sizeof(sockaddr)))
{
closesocket(s);
printf("Could not connect socket : %d" , WSAGetLastError());
}
WSAEventSelect(s, hSocketEvent, FD_READ);
do
{
//events[0] = hSocketEvent;
//events[1] = hSomeEvent;
//result = WaitForMultipleObjects(2, events, FALSE, 1000);
evtPtr = &hSocketEvent;
result = WaitForMultipleObjects(1, evtPtr, FALSE, 1000);
switch (result)
{
case WAIT_OBJECT_0 + 0:
printf("hSocketEvent is signalled!\n");
len = recv(s, buff, sizeof(buff), 0);
printf(" %d bytes received\n", len);
WSAResetEvent(hSocketEvent);
break;
case WAIT_OBJECT_0 + 1:
printf("hSomeEvent is signalled!\n");
break;
case WAIT_TIMEOUT:
printf("timeout\n");
break;
default:
printf("error = %d\n", GetLastError());
break;
}
}
while (1);
printf("\n\nend.");
getch();
return (0);
}
#包括
#包括
#包括
#包括
#包括
#pragma注释(lib,“Ws2_32.lib”);
#定义服务器\u端口5000
处理突发事件;
处理hSocketEvent;
DWORD WINAPI事件线程(LPVOID pData)
{
而(1)
{
SleepEx(2250,假);
SetEvent(hSomeEvent);
}
返回(0);
}
DWORD WINAPI服务器线程(LPVOID pData)
{
套接字侦听器;
sockaddr中的结构sockaddr_;
整数大小;
套接字客户端;
侦听器=socket(AF_INET,SOCK_STREAM,0);
if(侦听器==无效的\u套接字)
{
printf(“无法创建套接字:%d”,WSAGetLastError());
}
sockaddr.sin_family=AF_INET;
sockaddr.sin\u addr.s\u addr=INADDR\u ANY;
sockaddr.sin_端口=htons(服务器_端口);
if(bind(listener,(struct sockaddr*)&sockaddr,sizeof(sockaddr))==SOCKET\u错误)
{
printf(“绑定失败,错误代码:%d”,WSAGetLastError());
}
听(听者1);
while(侦听器)
{
size=sizeof(结构sockaddr_in);
client=accept(侦听器,(结构sockaddr*)和sockaddr,&size);
printf(“已连接的客户端”);
while(客户端!=无效的\u套接字)
{
SleepEx(5000,假);
如果(发送(客户端“hello\0”,6,0)!=6)
{
closesocket(客户端);
关闭(客户端,2);
客户端=无效的\u套接字;
}
}
SetEvent(hSomeEvent);
}
返回(0);
}
int main()
{
WSADATA WSADATA;
处理事件[2];
德沃德结果;
插座;
结构主机*hp;
sockaddr中的结构sockaddr_;
内伦;
字符buff[1024*16];
手柄*evtPtr;
WSAStartup(MAKEWORD(2,2)和wsaData);
hSocketEvent=WSACreateEvent();
//hSocketEvent=CreateEvent(NULL、FALSE、FALSE,“套接字事件”);
hSomeEvent=CreateEvent(NULL、FALSE、FALSE,“某些事件”);
CreateThread(NULL、0、eventThread、NULL、0和结果);
CreateThread(NULL、0、serverThread、NULL、0和结果);
s=套接字(AF_INET,SOCK_STREAM,0);
if(s==无效的_套接字)
{
printf(“无法创建套接字:%d”,WSAGetLastError());
}
hp=gethostbyname(“127.0.0.1”);
sockaddr.sin\u addr.s\u addr=*((无符号长*)hp->h\u addr);
sockaddr.sin_family=AF_INET;
sockaddr.sin_端口=htons(服务器_端口);
if(连接(s,(struct sockaddr*)和sockaddr,sizeof(sockaddr)))
{
插座;
printf(“无法连接套接字:%d”,WSAGetLastError());
}
WSAEventSelect(s、hSocketEvent、FD_READ);
做
{
//事件[0]=hSocketEvent;
//事件[1]=hSomeEvent;
//结果=WaitForMultipleObjects(2,事件,FALSE,1000);
evtPtr=&hSocketEvent;
结果=WaitForMultipleObjects(1,evtPtr,FALSE,1000);
开关(结果)
{
案例等待对象0+0:
printf(“hSocketEvent发出信号!\n”);
len=recv(s,buff,sizeof(buff),0);
printf(“%d字节已接收\n”,len);
wsarestevent(hSocketEvent);
打破
案例等待对象0+1:
printf(“hSomeEvent发出信号!\n”);
打破
案例等待超时:
printf(“超时\n”);
打破
违约:
printf(“错误=%d\n”,GetLastError());
打破
}
}
而(1),;
printf(“\n\nend.”);
getch();
返回(0);
}
请注意,如果使用WSACreateEvent
,则必须在读取数据后手动重置事件(否则WaitForMultipleObjects(…)
将出错)。查看WSAEVENT
的声明,发现WSAEVENT
只是句柄的别名。这就解释了t
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#pragma comment(lib, "Ws2_32.lib");
#define SERVER_PORT 5000
HANDLE hSomeEvent;
HANDLE hSocketEvent;
DWORD WINAPI eventThread(LPVOID pData)
{
while (1)
{
SleepEx(2250, FALSE);
SetEvent(hSomeEvent);
}
return (0);
}
DWORD WINAPI serverThread(LPVOID pData)
{
SOCKET listener;
struct sockaddr_in sockaddr;
int size;
SOCKET client;
listener = socket(AF_INET, SOCK_STREAM, 0);
if (listener == INVALID_SOCKET)
{
printf("Could not create socket : %d" , WSAGetLastError());
}
sockaddr.sin_family = AF_INET;
sockaddr.sin_addr.s_addr = INADDR_ANY;
sockaddr.sin_port = htons(SERVER_PORT);
if (bind(listener, (struct sockaddr *)&sockaddr , sizeof(sockaddr)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d" , WSAGetLastError());
}
listen(listener, 1);
while (listener)
{
size = sizeof(struct sockaddr_in);
client = accept(listener, (struct sockaddr *)&sockaddr, &size);
printf("client connected\n");
while (client != INVALID_SOCKET)
{
SleepEx(5000, FALSE);
if (send(client, "hello\0", 6, 0) != 6)
{
closesocket(client);
shutdown(client, 2);
client = INVALID_SOCKET;
}
}
SetEvent(hSomeEvent);
}
return (0);
}
int main()
{
WSADATA wsaData;
HANDLE events[2];
DWORD result;
SOCKET s;
struct hostent *hp;
struct sockaddr_in sockaddr;
int len;
char buff[1024 * 16];
HANDLE *evtPtr;
WSAStartup(MAKEWORD(2, 2), &wsaData);
hSocketEvent = WSACreateEvent();
//hSocketEvent = CreateEvent(NULL, FALSE, FALSE, "socket_event");
hSomeEvent = CreateEvent(NULL, FALSE, FALSE, "some_event");
CreateThread(NULL, 0, eventThread, NULL, 0, &result);
CreateThread(NULL, 0, serverThread, NULL, 0, &result);
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == INVALID_SOCKET)
{
printf("Could not create socket : %d" , WSAGetLastError());
}
hp = gethostbyname("127.0.0.1");
sockaddr.sin_addr.s_addr = *((unsigned long*)hp->h_addr);
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(SERVER_PORT);
if (connect(s, (struct sockaddr*)&sockaddr, sizeof(sockaddr)))
{
closesocket(s);
printf("Could not connect socket : %d" , WSAGetLastError());
}
WSAEventSelect(s, hSocketEvent, FD_READ);
do
{
//events[0] = hSocketEvent;
//events[1] = hSomeEvent;
//result = WaitForMultipleObjects(2, events, FALSE, 1000);
evtPtr = &hSocketEvent;
result = WaitForMultipleObjects(1, evtPtr, FALSE, 1000);
switch (result)
{
case WAIT_OBJECT_0 + 0:
printf("hSocketEvent is signalled!\n");
len = recv(s, buff, sizeof(buff), 0);
printf(" %d bytes received\n", len);
WSAResetEvent(hSocketEvent);
break;
case WAIT_OBJECT_0 + 1:
printf("hSomeEvent is signalled!\n");
break;
case WAIT_TIMEOUT:
printf("timeout\n");
break;
default:
printf("error = %d\n", GetLastError());
break;
}
}
while (1);
printf("\n\nend.");
getch();
return (0);
}
sockEvent = WSAEventSelect(fd, sockEvent, FD_WRITE);
if (WSAEventSelect(fd, sockEvent, FD_WRITE) != 0) return SOCKET_ERROR;