📄 netapiwrappers.h
字号:
BOOL SetHandleState(LPDWORD lpMode, LPDWORD lpMaxCollectionCount = NULL, LPDWORD lpCollectDataTimeout = NULL) const
{
_ASSERTE(m_hPipe!=INVALID_HANDLE_VALUE);
return ::SetNamedPipeHandleState(m_hPipe, lpMode, lpMaxCollectionCount, lpCollectDataTimeout);
}
BOOL Peek(LPDWORD lpTotalBytesAvail, LPDWORD lpBytesLeftThisMessage = NULL, LPVOID lpBuffer = NULL, DWORD nBufferSize = 0, LPDWORD lpBytesRead = NULL) const
{
_ASSERTE(m_hPipe!=INVALID_HANDLE_VALUE);
return ::PeekNamedPipe(m_hPipe, lpBuffer, nBufferSize, lpBytesRead, lpTotalBytesAvail, lpBytesLeftThisMessage);
}
BOOL WaitForData(DWORD dwTimeOut=INFINITE)
{
_ASSERTE(m_hPipe!=INVALID_HANDLE_VALUE);
// NOTE: Remember to create pipe with FILE_FLAG_OVERLAPPED flag.
// Overlapped results are only supported on Windows NT.
if( m_hEvent == NULL ) m_hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
_ASSERTE(m_hEvent!=NULL);
::ResetEvent(m_hEvent);
OVERLAPPED Ovlap = { 0 };
Ovlap.hEvent = m_hEvent;
WORD w;
// Read 0 bytes to get overlapped result
if( ::ReadFile(m_hPipe, &w, 0, NULL, &Ovlap) == FALSE ) {
if( ::GetLastError() != ERROR_IO_PENDING ) return TRUE; // error?
}
DWORD ret = ::WaitForMultipleObjects(1, &m_hEvent, FALSE, dwTimeOut);
if( ret == WAIT_FAILED ) return TRUE;
if( ret == WAIT_TIMEOUT ) return FALSE;
// Check result
DWORD dwRead;
if( ::GetOverlappedResult(m_hPipe, &Ovlap, &dwRead, FALSE) == 0 ) return TRUE;
return TRUE;
}
DWORD GetAvailableDataCount() const
{
_ASSERTE(m_hPipe!=INVALID_HANDLE_VALUE);
DWORD dwAvailable;
if( ::PeekNamedPipe(m_hPipe, NULL, 0, NULL, &dwAvailable, NULL) == FALSE ) return 0;
return dwAvailable;
}
static BOOL WaitNamedPipe(LPCTSTR pstrName, DWORD dwTimeOut = NMPWAIT_WAIT_FOREVER)
{
_ASSERTE(!::IsBadStringPtr(pstrName,-1));
return ::WaitNamedPipe(pstrName, dwTimeOut);
}
operator HANDLE() const { return m_hPipe; }
};
/////////////////////////////////////////////////////////////////////////////
// TCP/IP
#ifndef _NO_WINSOCK
#ifndef _WINSOCK2API_
#include <winsock.h>
#pragma comment(lib, "wsock32.lib")
#endif
// defined in winsock2.h
#ifndef SD_BOTH
#define SD_BOTH 0x02
#endif
struct WSAInit
{
WSAInit(BYTE bMajor = 1, BYTE bMinor = 1, WSADATA *pData = NULL)
{
WSADATA dummy;
if( pData == NULL ) pData = &dummy;
::WSAStartup(MAKEWORD(bMajor,bMinor), pData);
}
~WSAInit()
{
::WSACleanup();
}
};
class CSocket
{
public:
SOCKET m_hSocket;
SOCKADDR_IN m_sockaddr;
CSocket(SOCKET hSocket = INVALID_SOCKET) : m_hSocket(hSocket)
{
}
~CSocket()
{
Close();
}
BOOL Create(u_short iPort, LPCTSTR pstrName = NULL, int iBacklog = 8)
{
// Pass NULL as 'pstrName' to bind to default IP interface
if( OpenSocket(iPort, pstrName) == FALSE ) return FALSE;
if( ::bind(m_hSocket, (PSOCKADDR) &m_sockaddr, sizeof(m_sockaddr)) == SOCKET_ERROR ) {
return FALSE;
}
return ::listen(m_hSocket, iBacklog) == 0;
}
BOOL Open(u_short iPort, LPCTSTR pstrName)
{
_ASSERTE(!::IsBadStringPtr(pstrName,-1));
if( OpenSocket(iPort, pstrName) == FALSE ) return FALSE;
if( ::connect(m_hSocket, (PSOCKADDR) &m_sockaddr, sizeof(m_sockaddr)) == SOCKET_ERROR ) {
return FALSE;
}
return TRUE;
}
BOOL OpenSocket(u_short iPort, LPCTSTR pstrName)
{
_ASSERTE(m_hSocket==INVALID_SOCKET);
_ASSERTE(iPort>0 && iPort<=49152); // NOTE: Port 1024 to 49152 are reseved for you, the rest if for web/ftp/nntp servers
m_hSocket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if( m_hSocket == INVALID_SOCKET ) return FALSE;
if( pstrName == NULL ) {
m_sockaddr.sin_addr.s_addr = INADDR_ANY;
}
else {
USES_CONVERSION;
LPCSTR pstrAddress = T2CA(pstrName);
m_sockaddr.sin_addr.s_addr = ::inet_addr(pstrAddress);
if( m_sockaddr.sin_addr.s_addr == INADDR_NONE ) {
PHOSTENT pHost = ::gethostbyname(pstrAddress);
if( pHost == NULL ) return FALSE;
::CopyMemory(&m_sockaddr.sin_addr, pHost->h_addr_list[0], pHost->h_length);
}
}
m_sockaddr.sin_family = AF_INET;
m_sockaddr.sin_port = ::htons(iPort);
return TRUE;
}
void Close()
{
if( m_hSocket == INVALID_SOCKET ) return;
::shutdown(m_hSocket, SD_BOTH);
::closesocket(m_hSocket);
m_hSocket = INVALID_SOCKET;
return;
}
SOCKET Accept(PSOCKADDR pClient, int *pAddrSize)
{
_ASSERTE(pClient);
_ASSERTE(pAddrSize);
return ::accept(m_hSocket, pClient, pAddrSize);
}
BOOL IsNull() const
{
return m_hSocket == INVALID_SOCKET;
}
void Attach(SOCKET hSocket)
{
_ASSERTE(m_hSocket==INVALID_SOCKET);
m_hSocket = hSocket;
}
SOCKET Detach()
{
SOCKET hSocket = m_hSocket;
m_hSocket = INVALID_SOCKET;
return hSocket;
}
BOOL Read(LPVOID pData, DWORD dwSize, LPDWORD pdwRead = NULL, int iFlags = 0)
{
_ASSERTE(m_hSocket!=INVALID_SOCKET);
_ASSERTE(!::IsBadWritePtr(pData,dwSize));
// NOTE: You should always check the 'pdwRead' argument since
// large data may be split up in frames.
if( pdwRead != NULL ) *pdwRead = 0;
int ret = ::recv(m_hSocket, (char*) pData, dwSize, iFlags);
if( ret == 0 ) return FALSE; // Closed
if( ret == SOCKET_ERROR ) return FALSE;
if( pdwRead != NULL ) *pdwRead = ret;
return TRUE;
}
BOOL Write(LPCVOID pData, DWORD dwSize, LPDWORD pdwWritten = NULL, int iFlags = 0)
{
_ASSERTE(m_hSocket!=INVALID_SOCKET);
_ASSERTE(!::IsBadReadPtr(pData,dwSize));
if( pdwWritten != NULL ) *pdwWritten = 0;
// Streaming TCP/IP may not send all data at once
int iLeft = (int) dwSize;
int iPos = 0;
while( iLeft > 0 ) {
int ret = ::send(m_hSocket, (char*) pData + iPos, iLeft, iFlags);
if( ret == SOCKET_ERROR ) {
return FALSE;
}
iLeft -= ret;
iPos += ret;
}
if( pdwWritten != NULL ) *pdwWritten = dwSize;
return TRUE;
}
BOOL WaitForData(DWORD dwTimeOut = 0) const
{
_ASSERTE(m_hSocket!=INVALID_SOCKET);
TIMEVAL tm = { 0, dwTimeOut };
while( true ) {
fd_set fdread;
FD_ZERO(&fdread);
FD_SET(m_hSocket, &fdread);
int ret = ::select(0, &fdread, NULL, NULL, dwTimeOut == 0 ? NULL : &tm);
switch( ret ) {
case 0:
return FALSE; // timeout
case SOCKET_ERROR:
if( ::WSAGetLastError() == WSAEINPROGRESS ) return FALSE; // busy
// BUG: Hmm, this causes the code to continue and the next Read() to fail
return TRUE;
case 1:
if( FD_ISSET(m_hSocket, &fdread) ) return TRUE;
// FALL THROUGH...
default:
_ASSERTE(false);
}
}
}
BOOL WaitForSendReady(DWORD dwTimeOut = 0) const
{
_ASSERTE(m_hSocket!=INVALID_SOCKET);
TIMEVAL tm = { 0, dwTimeOut };
while( true ) {
fd_set fdsend;
FD_ZERO(&fdsend);
FD_SET(m_hSocket, &fdsend);
int ret = ::select(0, NULL, &fdsend, NULL, dwTimeOut == 0 ? NULL : &tm);
switch( ret ) {
case 0:
return FALSE; // timeout
case SOCKET_ERROR:
if( ::WSAGetLastError() == WSAEINPROGRESS ) return FALSE; // busy
// BUG: Hmm, this causes the code to continue and the next Send() to fail
return TRUE;
case 1:
if( FD_ISSET(m_hSocket, &fdsend) ) return TRUE;
// FALL THROUGH...
default:
_ASSERTE(false);
}
}
}
DWORD GetAvailableDataCount() const
{
_ASSERTE(m_hSocket!=INVALID_SOCKET);
// NOTE: See Q192599 why this is a bad idea!
u_long ulRead;
if( ::ioctlsocket(m_hSocket, FIONREAD, &ulRead) != 0 ) return 0;
return (DWORD) ulRead;
}
operator SOCKET() const { return m_hSocket; }
};
#endif // _NO_WINSOCK
#endif // !defined(AFX_PROTOCOLWRAPPERS_H__20010923_BB2C_8F54_F0B7_0080AD509054__INCLUDED_)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -