在第八章的源码中,为什么这些程序一连接就WSARecv()?
另外,我把最开始的WASRecv()删掉后发现,用dos下的telnet命令连接后输入数据都是白色的下划线。如果不去除WSARecv()就没有白色下划线。去除WSARecv的结果:
没有去除WSARecv的结果:
都是乱打了一些字符,另外,如果没有在socket连接后加WASRecv(),则在连接结束后没有程序的提示:
高手指教!谢谢。源码(复制粘贴的,是配套源码的原版)
// Module Name: callback.cpp
//
// Description:
//
// This sample illustrates how to develop a simple echo server Winsock
// application using the Overlapped I/O model with callback routines.
// This sample is implemented as a console-style application and simply prints
// messages when connections are established and removed from the server.
// The application listens for TCP connections on port 5150 and accepts them
// as they arrive. When this application receives data from a client, it
// simply echos (this is why we call it an echo server) the data back in
// it's original form until the client closes the connection.
//
// Compile:
//
// cl -o callback callback.cpp ws2_32.lib
//
// Command Line Options:
//
// callback.exe
//
// Note: There are no command line options for this sample.#include <winsock2.h>
#include <windows.h>
#include <stdio.h>#define PORT 5150
#define DATA_BUFSIZE 8192typedef 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;
}
}
}
}
另外,我把最开始的WASRecv()删掉后发现,用dos下的telnet命令连接后输入数据都是白色的下划线。如果不去除WSARecv()就没有白色下划线。去除WSARecv的结果:
没有去除WSARecv的结果:
都是乱打了一些字符,另外,如果没有在socket连接后加WASRecv(),则在连接结束后没有程序的提示:
高手指教!谢谢。源码(复制粘贴的,是配套源码的原版)
// Module Name: callback.cpp
//
// Description:
//
// This sample illustrates how to develop a simple echo server Winsock
// application using the Overlapped I/O model with callback routines.
// This sample is implemented as a console-style application and simply prints
// messages when connections are established and removed from the server.
// The application listens for TCP connections on port 5150 and accepts them
// as they arrive. When this application receives data from a client, it
// simply echos (this is why we call it an echo server) the data back in
// it's original form until the client closes the connection.
//
// Compile:
//
// cl -o callback callback.cpp ws2_32.lib
//
// Command Line Options:
//
// callback.exe
//
// Note: There are no command line options for this sample.#include <winsock2.h>
#include <windows.h>
#include <stdio.h>#define PORT 5150
#define DATA_BUFSIZE 8192typedef 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;
}
}
}
}
http://download.csdn.net/detail/geoff08zhang/4571358
迷惑,短路中……这个WSARecv是用来调用WorkerRoutine的么?
若没有和保安打招呼, 保安就回拦住他, 而且保安不会通知我, 我在家等一天也白等WSARecv就相当于和保安打招呼