在windows上使用套接字以外的其他对象进行选择

在windows上使用套接字以外的其他对象进行选择,windows,Windows,在套接字+管道上执行select()调用时,我遇到了一个问题 我知道已经有一些关于这方面的话题了,但是我读了很多东西和它们的反面,我不知道什么是解决我问题的最佳方法 对我来说最好的方法是使用WaitForMultipleObjects()侦听这两个对象,但是当我尝试仅在WSAEvent对象上调用它时,它失败了,最后一个错误捕获是代码6(无效句柄) 因此WaitForMultipleObjects似乎不适用于WinSocks事件,但是我已经在网上看到了一些使用它的示例。 WSACreateEven

在套接字+管道上执行select()调用时,我遇到了一个问题

我知道已经有一些关于这方面的话题了,但是我读了很多东西和它们的反面,我不知道什么是解决我问题的最佳方法

对我来说最好的方法是使用WaitForMultipleObjects()侦听这两个对象,但是当我尝试仅在WSAEvent对象上调用它时,它失败了,最后一个错误捕获是代码6(无效句柄)

因此WaitForMultipleObjects似乎不适用于WinSocks事件,但是我已经在网上看到了一些使用它的示例。 WSACreateEvent文档()的第二部分说:

Windows Sockets 2事件对象是Windows中的系统对象 环境。因此,如果Windows应用程序希望使用 自动重置事件而不是手动重置事件,应用程序可以 直接调用CreateEvent函数

这并不意味着WSAEvent基于常规windows事件?如果是这样,为什么它不能与WaitForMultipleObjects一起工作?医生说它可以处理常规事件


感谢您的帮助。

查看
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;