#pragma once
#include <WinSock2.h>// for socklib
#include <afxmt.h>// for lock
#include <cstdlib>
#include <cstring>
#include <string>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
#define WSA_RET_OK (0)
#define SS_START (WM_USER + 100)
#define SS_END (SS_START + 100)
#define SS_NOT_INIT (SS_START + 1)
#define SS_LOAD_LIB_OK (SS_START + 2)
#define SS_INIT_OK (SS_END - 1)
#define ERROR_START (WM_USER + 1000)
#define ERROR_LOAD_WS32_LIB_FAIL (ERROR_START + 1) // 加载网络库失败
#define ERROR_WS32_LIB_VESION_ERROR (ERROR_START + 2) // 网络库版本不匹配
#define MESSAGE_BUF_LENGTH (1024*10)
#define REGISTER_SOCKET_EVENTS (FD_READ | FD_CLOSE)
struct st_socket_event
{
WSAEVENT m_sockevent;
WSAEVENT m_threadExitEvent;
};
class st_sock_message
{
public:
st_sock_message():m_length(0),m_message(nullptr){}
st_sock_message(const char *arr, const int len) :m_length(len)
{
m_message = new char[m_length];
memcpy(m_message, arr, sizeof(char)*m_length);
}
~st_sock_message() { delete[] m_message; }
st_sock_message &operator=(const st_sock_message &rhl)
{
if (m_message == rhl.m_message)
{
return *this;
}
delete[] m_message;
m_length = rhl.m_length;
m_message = new char[m_length];
memcpy(m_message, rhl.m_message, sizeof(char)*m_length);
return *this;
}
private:
int m_length;
char *m_message;
};
typedef CArray<st_sock_message, st_sock_message &> stSockMessageArray;
class CAsynSocket
{
public:
CAsynSocket(const string &strIp);
~CAsynSocket();
bool fnConnect();
private:
bool fnWsaStartUp();
bool fnCreateSockThread();
static DWORD WINAPI fnSocketThreadProc(void *lparam);
bool fnCreateSocket();
bool fnCreateEvents();
bool fnOnRead(const int ierrorcode);
char m_msgBuf[MESSAGE_BUF_LENGTH];
SOCKET m_sockHandle;
HANDLE m_hThreadHandle;
INT m_nSocketStatus;
int m_iErrorCode;
st_socket_event m_events;
string m_strIp;
string m_strPort;
static const string m_strSplit;
stSockMessageArray m_sockMessageArray;
CCriticalSection m_msgLock;
};
#include "stdafx.h"
#include "AsynSocket.h"
const std::string CAsynSocket::m_strSplit = ":";
CAsynSocket::CAsynSocket(const string &strIp)
{
string::size_type pos = strIp.find(m_strSplit);
if (string::npos != pos)
{
m_strIp = strIp.substr(pos);
m_strPort = strIp.substr(pos + 1);
}
m_sockHandle = INVALID_SOCKET;
m_hThreadHandle = NULL;
m_iErrorCode = ERROR_START;
}
CAsynSocket::~CAsynSocket()
{
}
bool CAsynSocket::fnWsaStartUp()
{
WSADATA data;
int iRet = WSAStartup(MAKEWORD(2,2),&data);
if (iRet != WSA_RET_OK)
{
m_iErrorCode = ERROR_LOAD_WS32_LIB_FAIL;
return false;
}
if (HIBYTE(data.wVersion) != 2 || LOBYTE(data.wVersion) != 2)
{
WSACleanup();
m_iErrorCode = ERROR_WS32_LIB_VESION_ERROR;
return false;
}
m_nSocketStatus = SS_LOAD_LIB_OK;
return true;
}
bool CAsynSocket::fnConnect()
{
if (!fnWsaStartUp())
{
return false;
}
if (!fnCreateSockThread())
{
return false;
}
if (!fnCreateSocket())
{
return false;
}
return true;
}
bool CAsynSocket::fnCreateSockThread()
{
if (!fnCreateEvents())
{
return false;
}
m_hThreadHandle = CreateThread(0, 0, fnSocketThreadProc, this, 0, 0);
if (m_hThreadHandle == nullptr)
{
return false;
}
return true;
}
DWORD WINAPI CAsynSocket::fnSocketThreadProc(void *lparam)
{
CAsynSocket *psocket = (CAsynSocket *)lparam;
if (psocket == nullptr)
{
return false;
}
WSAEVENT pevents[] = { psocket->m_events.m_threadExitEvent,psocket->m_events.m_sockevent };
WSANETWORKEVENTS netevents;
DWORD dwRet = 0;
while (true)
{
dwRet = WSAWaitForMultipleEvents(2, pevents, FALSE, WSA_INFINITE, FALSE);
if (dwRet == WSA_WAIT_FAILED)
{
break;
}
if (dwRet == WSA_WAIT_EVENT_0)
{
break;
}
if (dwRet == (WSA_WAIT_EVENT_0 + 1))
{
dwRet = WSAEnumNetworkEvents(psocket->m_sockHandle, psocket->m_events.m_sockevent, &netevents);
if (dwRet != WSA_RET_OK)
{
continue;
}
if (netevents.lNetworkEvents & FD_READ)
{
psocket->fnOnRead(netevents.iErrorCode[FD_READ_BIT]);
}
if (netevents.lNetworkEvents & FD_CLOSE)
{
break;
}
}
}
return 0;
}
bool CAsynSocket::fnCreateSocket()
{
if (m_strIp.empty() || m_strPort.empty())
{
return false;
}
sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(atoi(m_strPort.c_str()));
addr.sin_addr.S_un.S_addr = inet_addr(m_strIp.c_str());
if (addr.sin_addr.S_un.S_addr == 0xFFFFFFFF)
{
return false;
}
m_sockHandle = socket(AF_INET, SOCK_STREAM, 0);
if (m_sockHandle == INVALID_SOCKET)
{
return false;
}
BOOL bOpt = FALSE;
if (WSA_RET_OK != setsockopt(m_sockHandle, SOL_SOCKET,SO_DONTLINGER,(const char *)&bOpt,sizeof(bOpt)))
{
return false;
}
if (WSA_RET_OK != setsockopt(m_sockHandle, SOL_SOCKET, SO_DONTROUTE, (const char *)&bOpt, sizeof(bOpt)))
{
return false;
}
if (WSA_RET_OK != setsockopt(m_sockHandle, IPPROTO_TCP, TCP_NODELAY, (const char *)&bOpt, sizeof(bOpt)))
{
return false;
}
if (WSA_RET_OK != connect(m_sockHandle,(const sockaddr *)&addr,sizeof(addr)))
{
return false;
}
if (WSA_RET_OK != WSAEventSelect(m_sockHandle, m_events.m_sockevent, REGISTER_SOCKET_EVENTS))
{
return false;
}
return true;
}
bool CAsynSocket::fnCreateEvents()
{
m_events.m_sockevent = WSACreateEvent();
m_events.m_threadExitEvent = WSACreateEvent();
if (m_events.m_sockevent == WSA_INVALID_EVENT || m_events.m_threadExitEvent == WSA_INVALID_EVENT)
{
return false;
}
return true;
}
bool CAsynSocket::fnOnRead(const int ierrorcode)
{
return true;
}