📄 cnet.cpp
字号:
// Cnet.cpp: implementation of the CCnet class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "BWChess.h"
#include "Cnet.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define BACKLOG 10
#define TIMEOUT 10
long CNetworking::m_count = 0;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CNetworking::CNetworking () : m_lasterror (0)
{
if (m_count == 0 && CConnection::m_count == 0)
{
WSADATA wsd;
int err;
err = WSAStartup (MAKEWORD (1, 1), &wsd);
if (err != 0)
throw CError (err);
}
hAcceptEvent = NULL;
hAcceptFunc = NULL;
dwAcceptThreadID = 0;
hAcceptThread = NULL;
m_socket = INVALID_SOCKET;
m_count ++;
}
CNetworking::~CNetworking ()
{
StopListen ();
if (m_count == 1 && CConnection::m_count == 0)
WSACleanup();
m_count --;
}
void CNetworking::SetLastError (long err)
{
m_sync.Enter ();
m_lasterror.m_number = err;
m_sync.Leave ();
}
void CNetworking::GetLastError (char* str, long len)
{
m_sync.Enter ();
m_lasterror.GetErrorString (str, len);
m_sync.Leave ();
}
bool CNetworking::Listen (int port)
{
if (IsListening ())
StopListen ();
sockaddr_in addr;
SOCKET sock;
sock = socket(AF_INET, SOCK_STREAM, 0); // Create socket
addr.sin_family = AF_INET; // Address family Internet
addr.sin_port = htons ((u_short)port); // Assign port 'port' to this socket
addr.sin_addr.s_addr = htonl (INADDR_ANY); // No destination
if (bind (sock, (LPSOCKADDR) &addr, sizeof (addr)) == SOCKET_ERROR)
{
closesocket (sock);
long err = WSAGetLastError ();
CNetworking::SetLastError (err);
return false;
}
if (listen (sock, BACKLOG) == SOCKET_ERROR)
{
closesocket (sock);
long err = WSAGetLastError ();
CNetworking::SetLastError (err);
return false;
}
m_sync.Enter ();
m_socket = sock;
m_addr = addr;
m_sync.Leave ();
hAcceptThread = CreateThread (NULL,
0,
(LPTHREAD_START_ROUTINE) AcceptThread,
this,
0,
(LPDWORD) &dwAcceptThreadID);
if (!hAcceptThread)
{
StopListen ();
return false;
}
return true;
}
void CNetworking::StopListen ()
{
if (!IsListening ())
{
CNetworking::SetLastError (WSAENOTCONN);
return;
}
m_sync.Enter ();
closesocket (m_socket);
m_socket = INVALID_SOCKET;
m_sync.Leave ();
WaitForSingleObject (hAcceptThread, INFINITE);
}
void CNetworking::SetAcceptFunc (CALLBACKFUNC hFunc)
{
m_sync.Enter ();
hAcceptFunc = hFunc;
m_sync.Leave ();
}
void CNetworking::SetAcceptEvent (HANDLE hEvent)
{
m_sync.Enter ();
hAcceptEvent = hEvent;
m_sync.Leave ();
}
CConnection* CNetworking::GetAccepted ()
{
CConnection* cAccepted;
m_sync.Enter ();
cAccepted = m_accepted.Remove ();
m_sync.Leave ();
return cAccepted;
}
int CNetworking::HasAccepted ()
{
int iAccepted;
m_sync.Enter ();
iAccepted = m_accepted.Length ();
m_sync.Leave ();
return iAccepted;
}
bool CNetworking::IsListening ()
{
bool bListening;
m_sync.Enter ();
bListening = m_socket != INVALID_SOCKET;
m_sync.Leave ();
return bListening;
}
int CNetworking::AcceptWait ()
{
int addr_size = sizeof (sockaddr_in);
SOCKET lsock;
SOCKET csock = INVALID_SOCKET;
sockaddr_in caddr = { 0 };
m_sync.Enter ();
lsock = m_socket;
m_sync.Leave ();
while (IsListening ())
{
m_sync.Enter ();
bool bRightSock = (lsock == m_socket);
m_sync.Leave ();
if (!bRightSock) return 1;
csock = accept (lsock, (LPSOCKADDR) &caddr, &addr_size); // accept a connection
if (csock == INVALID_SOCKET)
{
int aErr = WSAGetLastError();
if (aErr == WSAEINTR)
{
StopListen ();
return 1;
}
else
{
// error: could not accept
long err = WSAGetLastError ();
CNetworking::SetLastError (err);
StopListen ();
return 1;
}
}
else
{
CConnection* cAccepted = new CConnection ();
cAccepted->m_socket = csock;
cAccepted->m_addr = caddr;
cAccepted->hRecvThread = CreateThread (NULL,
0,
(LPTHREAD_START_ROUTINE) cAccepted->RecvThread,
cAccepted,
0,
(LPDWORD) &cAccepted->dwRecvThreadID);
if (cAccepted->hRecvThread == NULL)
{
cAccepted->Disconnect ();
CNetworking::SetLastError (1002);
}
else
{
m_sync.Enter ();
m_accepted.Add (cAccepted);
HANDLE hEvent = hAcceptEvent;
CALLBACKFUNC fncCallback = hAcceptFunc;
m_sync.Leave ();
if (hEvent) SetEvent (hEvent); // if an event was given, pulse the event
if (fncCallback) (fncCallback) ((DWORD) this); // if a function ptr was given, call the function
}
}
}
return 0;
}
int CNetworking::AcceptThread (void* pThis)
{
return ((CNetworking*) (pThis))->AcceptWait ();
}
bool CNetworking::GetNeighborhood(char* names, int len)
{
DWORD status;
HANDLE hEnum;
DWORD cbBuffer = 16384;
DWORD cEntries = 0xffffffff;
LPNETRESOURCE lpnr;
DWORD namesLast = 0;
char nms[2048] = "";
status = WNetOpenEnum (RESOURCE_CONTEXT, RESOURCETYPE_ANY, 0, NULL, &hEnum);
if (status != NO_ERROR)
return false;
do
{
lpnr = (LPNETRESOURCE) GlobalAlloc (GPTR, cbBuffer);
status = WNetEnumResource (hEnum, &cEntries, lpnr, &cbBuffer);
if (status == NO_ERROR)
{
for(DWORD i = 0; i < cEntries; i++)
{
if (lpnr[i].lpRemoteName != NULL)
{ // it is a computer in the network...
if (lpnr[i].lpRemoteName[0] == '\\' && lpnr[i].lpRemoteName[1] == '\\')
{ // recheck, if it really is a computer (because of the "\\")
int rname_len = strlen (lpnr[i].lpRemoteName);
for (int j = 2; j < rname_len; j++)
nms[namesLast + j - 2] = lpnr[i].lpRemoteName[j];
namesLast += (rname_len - 2);
nms[namesLast] = 13;
namesLast++;
}
}
}
}
else if (status != ERROR_NO_MORE_ITEMS )
{
GlobalFree ((HGLOBAL) lpnr);
WNetCloseEnum (hEnum);
return false;
}
GlobalFree ((HGLOBAL) lpnr);
}
while (status != ERROR_NO_MORE_ITEMS);
WNetCloseEnum (hEnum);
memset (names, 0, len);
int uselen = 2048;
if (len < uselen) uselen = len;
memcpy (names, nms, uselen);
return true;
}
bool CNetworking::GetLocalName(char *localname, int len)
{
char locname[512] = "";
int status = gethostname (locname, 512);
if (status != 0)
{
long err = WSAGetLastError ();
CNetworking::SetLastError (err);
return false;
}
memset (localname, 0, len);
int uselen = strlen (locname) + 1;
if (uselen > len) uselen = len;
memcpy (localname, locname, uselen);
return true;
}
bool CNetworking::GetLocalIP(char *localip, int len)
{
char locname[512];
char locip[16];
if (!(GetLocalName(locname, 512) && ResolveIP(locname, locip, 16)))
return false;
// not raising an error, bcause GetLocalName or ResolveIP already did it
memset (localip, 0, len);
int uselen = strlen (locip) + 1;
if (len < uselen) uselen = len;
memcpy (localip, locip, uselen);
return true;
}
bool CNetworking::GetLocalIPs(char *localips, int len)
{
char locname[512] = "";
char locips[256] = "";
if (!GetLocalName(locname, 512) || !ResolveIPs(locname, locips, 256))
return false;
memset (localips, 0, len);
int uselen = strlen (locips) + 1;
if (len < uselen) uselen = len;
memcpy (localips, locips, uselen);
return true;
}
bool CNetworking::ResolveName(char *hostip, char *hostname, int len)
{
unsigned long hstaddr = inet_addr (hostip);
hostent* phe = gethostbyaddr ((char*) &hstaddr, sizeof (unsigned long), AF_INET);
if (phe == NULL)
{
long err = WSAGetLastError ();
CNetworking::SetLastError (err);
return false;
}
char *hstname = (char*) phe->h_name;
memset (hostname, 0, len);
int uselen = strlen (hstname) + 1;
if (len < uselen) uselen = len;
memcpy (hostname, hstname, uselen);
return true;
}
bool CNetworking::ResolveIP(char *hostname, char *hostip, int len)
{
hostent* phe = gethostbyname (hostname);
if (phe == NULL)
{
long err = WSAGetLastError ();
CNetworking::SetLastError (err);
return false;
}
char hstip[15] = "";
if (phe->h_addr_list[0] != NULL)
{
sprintf (hstip, "%u.%u.%u.%u",
(unsigned char) phe->h_addr_list[0][0],
(unsigned char) phe->h_addr_list[0][1],
(unsigned char) phe->h_addr_list[0][2],
(unsigned char) phe->h_addr_list[0][3]);
}
else
{
long err = WSAGetLastError ();
CNetworking::SetLastError (err);
return false;
}
memset (hostip, 0, len);
int uselen = strlen (hstip) + 1;
if (len < uselen) uselen = len;
memcpy (hostip, hstip, uselen);
return true;
}
bool CNetworking::ResolveIPs(char *hostname, char *hostips, int len)
{
hostent *phe = gethostbyname (hostname);
char allips[256], null_ip[256];
if (phe == NULL || phe->h_addr_list[0] == NULL)
{
long err = WSAGetLastError ();
CNetworking::SetLastError (err);
return false;
}
int count = 0,
i = 0;
for (i = 0; i < 256; i++)
{
allips[i] = 0;
null_ip[i] = 0;
}
while (phe->h_addr_list[count] != NULL && count * 15 < 240)
{
char oneip[15] = "";
for (i = 0; i < 15; i++)
oneip[i] = 0;
sprintf(oneip, "%u.%u.%u.%u",
(unsigned char) phe->h_addr_list[count][0],
(unsigned char) phe->h_addr_list[count][1],
(unsigned char) phe->h_addr_list[count][2],
(unsigned char) phe->h_addr_list[count][3]);
for (i = (count * 15); i < (count * 15 + 15); i++)
null_ip[i] = oneip[i % 15];
count++;
}
int lEnd = 0;
for (i = 0; i < 15; i++)
{
if (null_ip[i * 15] == 0) break;
for (int j = 0; j < 15; j++)
allips[lEnd + j] = null_ip[i * 15 + j];
lEnd = strlen(allips);
allips[lEnd] = 13;
lEnd ++;
}
for (i = 0; i < len; i++)
hostips[i] = 0;
int uselen = strlen(allips);
if (uselen > len) uselen = len;
for (i = 0; i < uselen; i++)
hostips[i] = allips[i];
hostips[uselen] = 0;
return true;
}
long CConnection::m_count = 0;
CConnection::CConnection () : m_lasterror (0)
{
if (m_count == 0 && CNetworking::m_count == 0)
{
WSADATA wsd;
int err;
err = WSAStartup (MAKEWORD (1, 1), &wsd);
if (err != 0)
throw CError (err);
}
m_lasterror.m_number = 0;
m_event = CreateEvent (NULL, TRUE, FALSE, NULL);
hCloseEvent = NULL;
hCloseFunc = NULL;
hRecvEvent = NULL;
hRecvFunc = NULL;
dwRecvThreadID = 0;
hRecvThread = NULL;
m_socket = INVALID_SOCKET;
m_count ++;
}
CConnection::CConnection (const char* host, unsigned short port) : m_lasterror (0)
{
if (m_count == 0 && CNetworking::m_count == 0)
{
WSADATA wsd;
int err;
err = WSAStartup (MAKEWORD (1, 1), &wsd);
if (err != 0)
throw CError (err);
}
m_event = CreateEvent (NULL, TRUE, FALSE, NULL);
hCloseEvent = NULL;
hCloseFunc = NULL;
hRecvEvent = NULL;
hRecvFunc = NULL;
dwRecvThreadID = 0;
hRecvThread = NULL;
m_socket = INVALID_SOCKET;
m_count ++;
if (!Connect (host, port))
{
long err = WSAGetLastError ();
if (err == 0)
err = m_lasterror.m_number;
throw CError (err);
}
}
CConnection::~CConnection ()
{
Disconnect ();
if (m_count == 1 && CNetworking::m_count == 0)
WSACleanup();
CloseHandle (m_event);
m_count --;
}
void CConnection::SetLastError (long err)
{
m_sync.Enter ();
m_lasterror.m_number = err;
m_sync.Leave ();
}
void CConnection::GetLastError (char* str, long len)
{
m_sync.Enter ();
m_lasterror.GetErrorString (str, len);
m_sync.Leave ();
}
bool CConnection::Connect (const char* host, unsigned short port)
{
Disconnect ();
sockaddr_in addr;
SOCKET sock;
sock = socket (AF_INET, SOCK_STREAM, 0); // create socket
addr.sin_family = AF_INET; // address family Internet
addr.sin_port = htons (port); // set server port number
addr.sin_addr.s_addr = inet_addr (host); // set server IP
if (connect (sock, (LPSOCKADDR) &addr, sizeof (addr)) == SOCKET_ERROR)
{
long err = WSAGetLastError ();
CConnection::SetLastError (err);
return false;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -