CALLBACK函数何时被系统调用?

xiaohuo 2002-05-07 03:28:00
CALLBACK函数何时被系统调用?
或者说,满足何种条件时,系统调用CALLBACK函数?

...全文
27 点赞 收藏 4
写回复
4 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
xiaohuo 2002-05-07
WorkerThread(LPVOID lpParameter)中参数lpParameter指向的是不是AcceptEvent?
回复
webber84 2002-05-07
WorkerRoutine:当接收操作完成的时候被调用。
WorkerThread:这是一个线程函数,当调用CreateThread后开始执行它的代码。
回复
xiaohuo 2002-05-07
我正在看《Windows网络编程技术》,第八章winsock I/O方法的例子。
如下:请问WorkerRutine(),WorkerThread是何时调用的满足什么条件时被调用的。


#include <winsock2.h>
#include <windows.h>
#include <stdio.h>

#define PORT 5150
#define DATA_BUFSIZE 8192

typedef struct _SOCKET_INFORMATION {
OVERLAPPED Overlapped;
SOCKET Socket;
CHAR Buffer[DATA_BUFSIZE];
WSABUF DataBuf;
DWORD BytesSEND;
DWORD BytesRECV;
} SOCKET_INFORMATION, * LPSOCKET_INFORMATION;

void CALLBACK WorkerRoutine(DWORD Error, DWORD BytesTransferred,
LPWSAOVERLAPPED Overlapped, DWORD InFlags);

DWORD WINAPI WorkerThread(LPVOID lpParameter);

SOCKET AcceptSocket;

void main(void)
{
WSADATA wsaData;
SOCKET ListenSocket;
SOCKADDR_IN InternetAddr;
INT Ret;
HANDLE ThreadHandle;
DWORD ThreadId;
WSAEVENT AcceptEvent;

if ((Ret = WSAStartup(0x0202,&wsaData)) != 0)
{
printf("WSAStartup failed with error %d\n", Ret);
WSACleanup();
return;
}

if ((ListenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0,
WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf("Failed to get a socket %d\n", WSAGetLastError());
return;
}

InternetAddr.sin_family = AF_INET;
InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
InternetAddr.sin_port = htons(PORT);

if (bind(ListenSocket, (PSOCKADDR) &InternetAddr,
sizeof(InternetAddr)) == SOCKET_ERROR)
{
printf("bind() failed with error %d\n", WSAGetLastError());
return;
}

if (listen(ListenSocket, 5))
{
printf("listen() failed with error %d\n", WSAGetLastError());
return;
}

if ((AcceptEvent = WSACreateEvent()) == WSA_INVALID_EVENT)
{
printf("WSACreateEvent() failed with error %d\n", WSAGetLastError());
return;
}

// Create a worker thread to service completed I/O requests.

if ((ThreadHandle = CreateThread(NULL, 0, WorkerThread, (LPVOID) AcceptEvent, 0, &ThreadId)) == NULL)
{
printf("CreateThread failed with error %d\n", GetLastError());
return;
}

while(TRUE)
{
AcceptSocket = accept(ListenSocket, NULL, NULL);

if (WSASetEvent(AcceptEvent) == FALSE)
{
printf("WSASetEvent failed with error %d\n", WSAGetLastError());
return;
}
}
}

DWORD WINAPI WorkerThread(LPVOID lpParameter)
{
DWORD Flags;
LPSOCKET_INFORMATION SocketInfo;
WSAEVENT EventArray[1];
DWORD Index;
DWORD RecvBytes;

// Save the accept event in the event array.

EventArray[0] = (WSAEVENT) lpParameter;

while(TRUE)
{
// Wait for accept() to signal an event and also process WorkerRoutine() returns.

while(TRUE)
{
Index = WSAWaitForMultipleEvents(1, EventArray, FALSE, WSA_INFINITE, TRUE);

if (Index == WSA_WAIT_FAILED)
{
printf("WSAWaitForMultipleEvents failed with error %d\n", WSAGetLastError());
return FALSE;
}

if (Index != WAIT_IO_COMPLETION)
{
// An accept() call event is ready - break the wait loop
break;
}
}

WSAResetEvent(EventArray[Index - WSA_WAIT_EVENT_0]);

// Create a socket information structure to associate with the accepted socket.

if ((SocketInfo = (LPSOCKET_INFORMATION) GlobalAlloc(GPTR,
sizeof(SOCKET_INFORMATION))) == NULL)
{
printf("GlobalAlloc() failed with error %d\n", GetLastError());
return FALSE;
}

// Fill in the details of our accepted socket.

SocketInfo->Socket = AcceptSocket;
ZeroMemory(&(SocketInfo->Overlapped), sizeof(WSAOVERLAPPED));
SocketInfo->BytesSEND = 0;
SocketInfo->BytesRECV = 0;
SocketInfo->DataBuf.len = DATA_BUFSIZE;
SocketInfo->DataBuf.buf = SocketInfo->Buffer;

Flags = 0;
if (WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &RecvBytes, &Flags,
&(SocketInfo->Overlapped), WorkerRoutine) == SOCKET_ERROR)
{
if (WSAGetLastError() != WSA_IO_PENDING)
{
printf("WSARecv() failed with error %d\n", WSAGetLastError());
return FALSE;
}
}

printf("Socket %d connected\n", AcceptSocket);
}

return TRUE;
}

void CALLBACK WorkerRoutine(DWORD Error, DWORD BytesTransferred,
LPWSAOVERLAPPED Overlapped, DWORD InFlags)
{
DWORD SendBytes, RecvBytes;
DWORD Flags;

// Reference the WSAOVERLAPPED structure as a SOCKET_INFORMATION structure
LPSOCKET_INFORMATION SI = (LPSOCKET_INFORMATION) Overlapped;

if (Error != 0)
{
printf("I/O operation failed with error %d\n", Error);
}

if (BytesTransferred == 0)
{
printf("Closing socket %d\n", SI->Socket);
}

if (Error != 0 || BytesTransferred == 0)
{
closesocket(SI->Socket);
GlobalFree(SI);
return;
}

// Check to see if the BytesRECV field equals zero. If this is so, then
// this means a WSARecv call just completed so update the BytesRECV field
// with the BytesTransferred value from the completed WSARecv() call.

if (SI->BytesRECV == 0)
{
SI->BytesRECV = BytesTransferred;
SI->BytesSEND = 0;
}
else
{
SI->BytesSEND += BytesTransferred;
}

if (SI->BytesRECV > SI->BytesSEND)
{

// Post another WSASend() request.
// Since WSASend() is not gauranteed to send all of the bytes requested,
// continue posting WSASend() calls until all received bytes are sent.

ZeroMemory(&(SI->Overlapped), sizeof(WSAOVERLAPPED));

SI->DataBuf.buf = SI->Buffer + SI->BytesSEND;
SI->DataBuf.len = SI->BytesRECV - SI->BytesSEND;

if (WSASend(SI->Socket, &(SI->DataBuf), 1, &SendBytes, 0,
&(SI->Overlapped), WorkerRoutine) == SOCKET_ERROR)
{
if (WSAGetLastError() != WSA_IO_PENDING)
{
printf("WSASend() failed with error %d\n", WSAGetLastError());
return;
}
}
}
else
{
SI->BytesRECV = 0;

// Now that there are no more bytes to send post another WSARecv() request.

Flags = 0;
ZeroMemory(&(SI->Overlapped), sizeof(WSAOVERLAPPED));

SI->DataBuf.len = DATA_BUFSIZE;
SI->DataBuf.buf = SI->Buffer;

if (WSARecv(SI->Socket, &(SI->DataBuf), 1, &RecvBytes, &Flags,
&(SI->Overlapped), WorkerRoutine) == SOCKET_ERROR)
{
if (WSAGetLastError() != WSA_IO_PENDING )
{
printf("WSARecv() failed with error %d\n", WSAGetLastError());
return;
}
}
}
}
回复
webber84 2002-05-07
不同的CALLBACK函数调用时机不同,你这样问怎么回答你呢?
回复
相关推荐
发帖
VC/MFC
创建于2007-09-28

1.5w+

社区成员

VC/MFC相关问题讨论
申请成为版主
帖子事件
创建了帖子
2002-05-07 03:28
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……