我在Windows套接字中使用WSAEventSelect I / O模型,现在我想知道我怎么知道我的发送和接收操作已经发送和接收了所有数据?
在我知道之后,我应该如何设计一种方式以便完全发送数据?任何例子都会非常感激。
这是代码(我正在学习的书中的示例代码):
SOCKET SocketArray [WSA_MAXIMUM_WAIT_EVENTS];
WSAEVENT EventArray [WSA_MAXIMUM_WAIT_EVENTS],
NewEvent;
SOCKADDR_IN InternetAddr;
SOCKET Accept, Listen;
DWORD EventTotal = 0;
DWORD Index, i;
WSANETWORKEVENTS NetworkEvents;
// Set up socket for listening etc...
// ....
NewEvent = WSACreateEvent();
WSAEventSelect(Listen, NewEvent,
FD_ACCEPT │ FD_CLOSE);
listen(Listen, 5);
SocketArray[EventTotal] = Listen;
EventArray[EventTotal] = NewEvent;
EventTotal++;
while(TRUE)
{
// Wait for network events on all sockets
Index = WSAWaitForMultipleEvents(EventTotal,
EventArray, FALSE, WSA_INFINITE, FALSE);
Index = Index - WSA_WAIT_EVENT_0;
// Iterate through all events to see if more than one is signaled
for(i=Index; i < EventTotal ;i++
{
Index = WSAWaitForMultipleEvents(1, &EventArray[i], TRUE, 1000,
FALSE);
if ((Index == WSA_WAIT_FAILED) ││ (Index == WSA_WAIT_TIMEOUT))
continue;
else
{
Index = i;
WSAEnumNetworkEvents(
SocketArray[Index],
EventArray[Index],
&NetworkEvents);
// Check for FD_ACCEPT messages
if (NetworkEvents.lNetworkEvents & FD_ACCEPT)
{
if (NetworkEvents.iErrorCode[FD_ACCEPT_BIT] != 0)
{
printf("FD_ACCEPT failed with error %d\n",
NetworkEvents.iErrorCode[FD_ACCEPT_BIT]);
break;
}
// Accept a new connection, and add it to the
// socket and event lists
Accept = accept(
SocketArray[Index],
NULL, NULL);
NewEvent = WSACreateEvent();
WSAEventSelect(Accept, NewEvent,
FD_READ │ FD_CLOSE);
EventArray[EventTotal] = NewEvent;
SocketArray[EventTotal] = Accept;
EventTotal++;
printf("Socket %d connected\n", Accept);
}
// Process FD_READ notification
if (NetworkEvents.lNetworkEvents & FD_READ)
{
if (NetworkEvents.iErrorCode[FD_READ_BIT] != 0)
{
printf("FD_READ failed with error %d\n",
NetworkEvents.iErrorCode[FD_READ_BIT]);
break;
}
// Read data from the socket
recv(SocketArray[Index - WSA_WAIT_EVENT_0],
buffer, sizeof(buffer), 0);
// here I do some processing on the data received
DoSomething(buffer);
// now I want to send data
send(SocketArray[Index - WSA_WAIT_EVENT_0],
buffer, sizeof(buffer), 0);
// how can I be assured that the data is sent completely
}
// FD_CLOSE handling here
// ......
// ......
}
}
}
我的想法是,我会设置一个布尔标志来确定接收已完成(消息将以其长度为前缀),然后开始处理该数据。但是发送()呢?你能告诉我可能性吗?
**编辑:**请参阅FD_READ事件部分
答案 0 :(得分:0)
除非您正在处理的协议(应用程序层)为您提供有关您将要接收的数据量的任何信息,否则确定是否没有更多要接收的数据的唯一方法是对等方断开连接。如果服务器只是停止发送,你无法确定它的结束或它只是忙。它结束时结束。您也无法确定服务器是否因为其结束而断开连接,或者因为连接已断开。
这就是为什么大多数协议通知对等方在发送之前要发送多少字节,或者在数据末尾放置一个边界。
关于发送,您必须了解您正在使用的缓冲区。当你send()
时,它会转到一个缓冲区(默认情况下为64KB)。 send()
返回缓冲区中放置的字节数,如果它少于您尝试发送的字节数,则必须在下次收到FD_WRITE事件时对其进行管理以再次尝试。
您无法确定对等方已收到多少数据,除非它通知您(mIRC DDC会这样做)。
不确定它让你的疑惑变得清晰,希望它有所帮助:)
答案 1 :(得分:0)