#include <SDKDDKVer.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <WinSock2.h>
#pragma comment(lib,"WS2_32.lib")
#pragma comment(lib,"msvcrt.lib")
#include <stdio.h>
#include <mswsock.h>
#include <MSTcpIP.h>
#include <process.h>
#define tcp_server_connt 1
#define tcp_server_recv 2
#define tcp_server_stop 3
#define tcp_server_send 4
#define tcp_server_close 5
#define tcp_client_connt 1
#define tcp_client_recv 2
#define tcp_client_send 4
#define tcp_client_close 5
#define tcp_len 65535
typedef void(__stdcall *onServer_ex)(HANDLE Server, SOCKET so, int type, char *buf, int len, int count);
typedef void(__stdcall *onClient_ex)(HANDLE Client, SOCKET so, int type, char *buf, int len);
extern int g_cpu;
extern int buf_len;
extern HANDLE hEvent_Server;
extern HANDLE hEvent_Client;
extern onServer_ex onServerFunc;
extern onClient_ex onClientFunc;
HANDLE hEvent_Server = NULL;
HANDLE hEvent_Client = NULL;
int g_cpu = 0;
int buf_len = 512;
onServer_ex onServerFunc = NULL;
onClient_ex onClientFunc = NULL;
int closesockets(SOCKET so);
int closesockets(SOCKET so) {
if (INVALID_SOCKET == so) {
return 0;
}
struct linger lingerStruct;
lingerStruct.l_onoff = 1;
lingerStruct.l_linger = 0;
setsockopt(so, SOL_SOCKET, SO_LINGER, (char *)&lingerStruct, sizeof(lingerStruct));
shutdown(so, SD_BOTH);
return closesocket(so);
}
bool __stdcall socket_local(char* ip) {
char hostname[256];
int ret = gethostname(hostname, sizeof(hostname));
if (ret == SOCKET_ERROR) {
return false;
}
HOSTENT* host = gethostbyname(hostname);
if (host == NULL) {
return false;
}
strcpy(ip, inet_ntoa(*(in_addr*)*host->h_addr_list));
return true;
}
class Socket_Server_IO;
typedef struct server_struct {
OVERLAPPED op;
Socket_Server_IO *so;
int state;
SOCKET c_so;
char *buf;
DWORD slen;
DWORD cb;
DWORD bufSize;
DWORD bufOffset;
} S_server_struct, *P_server_struct;
class Socket_Server_IO {
public:
Socket_Server_IO(void);
~Socket_Server_IO(void);
public:
int Init(char * host, unsigned short nPort, int nIsSC);
int AcceptServer();
int Accept();
void ClientAccept(bool error, P_server_struct op);
void RecvData(bool error, P_server_struct op);
int Close();
int doSend(SOCKET so, char* buf, DWORD cb);
int doSend_sync(SOCKET so, char* buf, DWORD cb);
void OnSend(bool ercode, P_server_struct op);
char* get_ip(SOCKET so) {
sockaddr_in in;
int len = sizeof(in);
getpeername(so, (sockaddr*)&in, &len);
return inet_ntoa(in.sin_addr);
}
SOCKET get_socket() {
return m_so;
}
u_short get_port() {
sockaddr_in in;
int len = sizeof(in);
getsockname(m_so, (sockaddr*)&in, &len);
return ntohs(in.sin_port);
}
char* get_addr(SOCKET m_so) {
sockaddr_in in;
int len = sizeof(in);
getsockname(m_so, (sockaddr*)&in, &len);
return inet_ntoa(in.sin_addr);
}
public:
SOCKET m_so;
int m_cnum;
CRITICAL_SECTION m_cs;
BOOL m_Is;
BOOL m_Close;
};
Socket_Server_IO::Socket_Server_IO(void) {
m_Close = FALSE;
InitializeCriticalSection(&m_cs);
m_cnum = 0;
m_so = INVALID_SOCKET;
}
Socket_Server_IO::~Socket_Server_IO(void) {
m_cnum = 0;
m_so = INVALID_SOCKET;
}
int Socket_Server_IO::Init(char * host, unsigned short nPort, int nIs) {
m_Is = nIs;
m_so = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, WSA_FLAG_OVERLAPPED);
if (INVALID_SOCKET == m_so) {
printf("Init->WSASocket \n");
return WSAGetLastError();
}
HANDLE t = CreateIoCompletionPort((HANDLE)m_so, hEvent_Server, 0, 0);
if (NULL == t) {
Close();
printf("Init->CreateIoCompletionPort \n");
return GetLastError();
}
sockaddr_in in;
in.sin_family = AF_INET;
in.sin_addr.S_un.S_addr = inet_addr(host);
in.sin_port = htons(nPort);
if (SOCKET_ERROR == bind(m_so, (SOCKADDR *)&in, sizeof (in))) {
printf("Init->bind \n");
Close();
return WSAGetLastError();
}
if (SOCKET_ERROR == listen(m_so, g_cpu)) {
Close();
return WSAGetLastError();
}
return AcceptServer();
}
int Socket_Server_IO::AcceptServer() {
server_struct *op = new server_struct;
memset(op, 0, sizeof(server_struct));
op->buf = new char[buf_len];
op->so = this;
op->bufSize = buf_len;
op->bufOffset = 0;
op->state = tcp_server_connt;
op->c_so = INVALID_SOCKET;
op->c_so = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, WSA_FLAG_OVERLAPPED);
if (INVALID_SOCKET == op->c_so) {
delete[]op->buf;
op->buf = NULL;
delete[]op;
op = NULL;
Close();
return WSAGetLastError();
}
//必须设置
setsockopt(op->c_so, SOL_SOCKET, SO_RCVBUF, (const char*)&buf_len, sizeof(int));
int nSendBuf = 0;
setsockopt(op->c_so, SOL_SOCKET, SO_SNDBUF, (const char*)&nSendBuf, sizeof(int));
BOOL bReuseaddr = TRUE;
setsockopt(op->c_so, SOL_SOCKET, SO_REUSEADDR, (const char*)&bReuseaddr, sizeof(BOOL));
HANDLE t = NULL;
t = CreateIoCompletionPort((HANDLE)op->c_so, hEvent_Server, 0, 0);
if (NULL == t) {
closesockets(op->c_so);
op->c_so = INVALID_SOCKET;
delete[]op->buf;
op->buf = NULL;
delete[]op;
op = NULL;
Close();
return GetLastError();
}
LPFN_ACCEPTEX lpfnAcceptEx = NULL;
GUID lGUID = WSAID_ACCEPTEX;
DWORD cb = 0;
if (WSAIoctl(m_so, SIO_GET_EXTENSION_FUNCTION_POINTER, &lGUID, sizeof(GUID), &lpfnAcceptEx, sizeof(lpfnAcceptEx), &cb, NULL, NULL)) {
closesockets(op->c_so);
op->c_so = INVALID_SOCKET;
delete[]op->buf;
op->buf = NULL;
delete[]op;
op = NULL;
Close();
return 2;
}
DWORD Cb = 0;
if (lpfnAcceptEx(m_so, op->c_so, op->buf, 0, sizeof(sockaddr) + 16, sizeof(sockaddr) + 16, &Cb, (LPOVERLAPPED)op)) {
closesockets(op->c_so);
op->c_so = INVALID_SOCKET;
delete[]op->buf;
op->buf = NULL;
delete[]op;
op = NULL;
Close();
return 3;
}
return 0;
}
int Socket_Server_IO::Close() {
m_Close = TRUE;
m_cnum = 0;
closesockets(m_so);
m_so = INVALID_SOCKET;
return 0;
}
int Socket_Server_IO::Accept() {
server_struct *op = new server_struct;
memset(op, 0, sizeof(server_struct));
op->buf = new char[buf_len];
op->so = this;
op->bufSize = buf_len;
op->bufOffset = 0;
op->state = tcp_server_connt;
op->c_so = INVALID_SOCKET;
op->c_so = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, WSA_FLAG_OVERLAPPED);
if (INVALID_SOCKET == op->c_so) {
delete[]op->buf;
op->buf = NULL;
delete[]op;
op = NULL;
return WSAGetLastError();
}
//必须设置
setsockopt(op->c_so, SOL_SOCKET, SO_RCVBUF, (const char*)&buf_len, sizeof(int));
int nSendBuf = 0;
setsockopt(op->c_so, SOL_SOCKET, SO_SNDBUF, (const char*)&nSendBuf, sizeof(int));
BOOL bReuseaddr = TRUE;
setsockopt(op->c_so, SOL_SOCKET, SO_REUSEADDR, (const char*)&bReuseaddr, sizeof(BOOL));
HANDLE t = NULL;
t = CreateIoCompletionPort((HANDLE)op->c_so, hEvent_Server, 0, 0);
if (NULL == t) {
closesockets(op->c_so);
op->c_so = INVALID_SOCKET;
PostQueuedCompletionStatus(hEvent_Server, 0, 0, (LPOVERLAPPED)op);
delete[]op->buf;
op->buf = NULL;
delete[]op;
op = NULL;
return GetLastError();
}
LPFN_ACCEPTEX lpfnAcceptEx = NULL;
GUID lGUID = WSAID_ACCEPTEX;
DWORD cb = 0;
if (WSAIoctl(m_so, SIO_GET_EXTENSION_FUNCTION_POINTER, &lGUID, sizeof(GUID), &lpfnAcceptEx, sizeof(lpfnAcceptEx), &cb, NULL, NULL)) {
closesockets(op->c_so);
op->c_so = INVALID_SOCKET;
PostQueuedCompletionStatus(hEvent_Server, 0, 0, (LPOVERLAPPED)op);
delete[]op->buf;
op->buf = NULL;
delete[]op;
op = NULL;
return 2;
}
DWORD Cb = 0;
if (lpfnAcceptEx(m_so, op->c_so, op->buf, 0, sizeof(sockaddr) + 16, sizeof(sockaddr) + 16, &Cb, (LPOVERLAPPED)op)) {
closesockets(op->c_so);
op->c_so = INVALID_SOCKET;
PostQueuedCompletionStatus(hEvent_Server, 0, 0, (LPOVERLAPPED)op);
delete[]op->buf;
op->buf = NULL;
delete[]op;
op = NULL;
return 3;
}
return 0;
}
void Socket_Server_IO::ClientAccept(bool error, P_server_struct nop) {
while (0 != Accept()) {
Sleep(1);
}
setsockopt(nop->c_so, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char*)&m_so, sizeof(SOCKET));
DWORD Cb = 0;
tcp_keepalive ka;
ka.onoff = 1;
ka.keepalivetime = 1000 * 30;
ka.keepaliveinterval = 1000 * 5;
WSAIoctl(nop->c_so, SIO_KEEPALIVE_VALS, &ka, sizeof(ka), NULL, 0, &Cb, NULL, NULL);
EnterCriticalSection(&m_cs);
m_cnum++;
LeaveCriticalSection(&m_cs);
onServerFunc(this, nop->c_so, tcp_server_connt, NULL, 0, m_cnum);
//如果该客户端进入就断开了
if (error) {
EnterCriticalSection(&m_cs);
m_cnum--;
LeaveCriticalSection(&m_cs);
onServerFunc(this, nop->c_so, tcp_server_close, NULL, 0, m_cnum);
closesockets(nop->c_so);
nop->c_so = INVALID_SOCKET;
delete[]nop->buf;
nop->buf = NULL;
delete nop;
nop = NULL;
return;
}
nop->state = tcp_server_recv;
WSABUF wsabuf;
if (m_Is) {
delete []nop->buf;
nop->bufOffset = 0;
nop->buf = new char[sizeof(DWORD)];
nop->bufSize = sizeof(DWORD);
wsabuf.buf = nop->buf + nop->bufOffset;
wsabuf.len = nop->bufSize - nop->bufOffset;
} else {
wsabuf.buf = nop->buf;
wsabuf.len = buf_len;
}
DWORD Flg = 0;
Cb = 0;
if (WSARecv(nop->c_so, &wsabuf, 1, &Cb, &Flg, (LPWSAOVERLAPPED)nop, NULL)) {
int ercode = WSAGetLastError();
if (ercode == WSAEFAULT) {
return;
} else if (ercode != WSA_IO_PENDING) {
EnterCriticalSection(&m_cs);
m_cnum--;
LeaveCriticalSection(&m_cs);
onServerFunc(this, nop->c_so, tcp_server_close, NULL, 0, m_cnum);
closesockets(nop->c_so);
nop->c_so = INVALID_SOCKET;
delete[]nop->buf;
nop->buf = NULL;
delete nop;
nop = NULL;
return;
}
}
}
void Socket_Server_IO::RecvData(bool error, P_server_struct nop) {
if (error) {
EnterCriticalSection(&m_cs);
m_cnum--;
LeaveCriticalSection(&m_cs);
onServerFunc(this, nop->c_so, tcp_server_close, 0, 0, m_cnum);
//closesockets(nop->c_so);
//nop->c_so = INVALID_SOCKET;
delete[]nop->buf;
nop->buf = NULL;
delete nop;
nop = NULL;
return;
}
if (m_Is) {
nop->bufOffset += nop->cb;
if (nop->bufOffset < nop->bufSize) {
nop->state = tcp_server_recv;
WSABUF wsabuf;
if (m_Is) {
wsabuf.buf = nop->buf + nop->bufOffset;
wsabuf.len = nop->bufSize - nop->bufOffset;
} else {
wsabuf.buf = nop->buf;
wsabuf.len = buf_len;
}
DWORD Cb = 0;
DWORD Flg = 0;
if (WSARecv(nop->c_so, &wsabuf, 1, &Cb, &Flg, (LPWSAOVERLAPPED)nop, NULL)) {
int ercode = WSAGetLastError();
if (ercode == WSAEFAULT) {
return;
} else if (ercode != WSA_IO_PENDING) {
EnterCriticalSection(&m_cs);
m_cnum--;
LeaveCriticalSection(&m_cs);
onServerFunc(this, nop->c_so, tcp_server_close, 0, 0, m_cnum);
delete[]nop->buf;
nop->buf = NULL;
delete nop;
nop = NULL;
return;
}
}
return;
}
DWORD size = *((DWORD*)(nop->buf));
if (size > 65536000) {
EnterCriticalSection(&m_cs);
m_cnum--;
LeaveCriticalSection(&m_cs);
onServerFunc(this, nop->c_so, tcp_server_close, 0, 0, m_cnum);
//closesockets(nop->c_so);
//nop->c_so = INVALID_SOCKET;
delete[]nop->buf;
nop->buf = NULL;
delete nop;
nop = NULL;
return;
}
if (nop->bufOffset < DWORD(sizeof(DWORD)) + size) { //完整性检测
delete[] nop->buf;
nop->buf = new char[sizeof(DWORD) + size];
nop->bufSize = sizeof(DWORD) + size;
nop->bufOffset = sizeof(DWORD);
memcpy(nop->buf, &size, sizeof(DWORD));
nop->state = tcp_server_recv;
WSABUF wsabuf;
if (m_Is) {
wsabuf.buf = nop->buf + nop->bufOffset;
wsabuf.len = nop->bufSize - nop->bufOffset;
} else {
wsabuf.buf = nop->buf;
wsabuf.len = buf_len;
}
DWORD Cb = 0;
DWORD Flg = 0;
if (WSARecv(nop->c_so, &wsabuf, 1, &Cb, &Flg, (LPWSAOVERLAPPED)nop, NULL)) {
int ercode = WSAGetLastError();
if (ercode == WSAEFAULT) {
return;
} else if (ercode != WSA_IO_PENDING) {
EnterCriticalSection(&m_cs);
m_cnum--;
LeaveCriticalSection(&m_cs);
onServerFunc(this, nop->c_so, tcp_server_close, 0, 0, m_cnum);
delete[]nop->buf;
nop->buf = NULL;
delete nop;
nop = NULL;
return;
}
}
return;
}
if (nop->bufSize - sizeof(DWORD) > 0) {
onServerFunc(this, nop->c_so, tcp_server_recv, nop->buf + sizeof(DWORD), nop->bufSize - sizeof(DWORD), m_cnum);
}
delete[]nop->buf;
nop->buf = new char[sizeof(DWORD)];
nop->bufSize = sizeof(DWORD);
} else {
onServerFunc(this, nop->c_so, tcp_server_recv, nop->buf, nop->cb, m_cnum);
}
nop->bufOffset = 0;
nop->state = tcp_server_recv;
WSABUF wsabuf;
if (m_Is) {
wsabuf.buf = nop->buf + nop->bufOffset;
wsabuf.len = nop->bufSize - nop->bufOffset;
} else {
wsabuf.buf = nop->buf;
wsabuf.len = buf_len;
}
DWORD Cb = 0;
DWORD Flg = 0;
if (WSARecv(nop->c_so, &wsabuf, 1, &Cb, &Flg, (LPWSAOVERLAPPED)nop, NULL)) {
int ercode = WSAGetLastError();
if (ercode == WSAEFAULT) {
return;
} else if (ercode != WSA_IO_PENDING) {
EnterCriticalSection(&m_cs);
m_cnum--;
LeaveCriticalSection(&m_cs);
onServerFunc(this, nop->c_so, tcp_server_close, 0, 0, m_cnum);
//closesocket(nop->c_so);
//nop->c_so = INVALID_SOCKET;
//PostQueuedCompletionStatus(hEvent_Server, 0, NULL, (LPOVERLAPPED)nop);
delete[]nop->buf;
nop->buf = NULL;
delete nop;
nop = NULL;
}
}
}
int Socket_Server_IO::doSend(SOCKET so, char* buf, DWORD cb) {
if (cb > 65536000) {
return 0;
}
server_struct *op = new server_struct;
memset(op, 0, sizeof(server_struct));
op->so = this;
op->state = tcp_server_send;
WSABUF wsabuf;
if (m_Is) {
op->buf = new char[sizeof(DWORD) + cb];
op->bufSize = sizeof(DWORD) + cb;
wsabuf.buf = op->buf;
wsabuf.len = op->bufSize;
memcpy(wsabuf.buf, &cb, sizeof(DWORD));
memcpy(wsabuf.buf + sizeof(DWORD), buf, cb);
} else {
wsabuf.buf = buf;
wsabuf.len = cb;
}
op->bufOffset = 0;
if (WSASend(so, &wsabuf, 1, &op->cb, 0, (LPWSAOVERLAPPED)op, NULL)) {
int ercode = WSAGetLastError();
if (ercode != WSA_IO_PENDING) {
delete[]op->buf;
op->buf = NULL;
delete op;
op = NULL;
return 1;
}
}
return 0;
}
int Socket_Server_IO::doSend_sync(SOCKET so, char* buf, DWORD cb) {
if (cb > 65536000) {
return 0;
}
if (m_Is) {
memcpy(buf, &cb, sizeof(DWORD));
memcpy(buf + sizeof(DWORD), buf, cb);
if (send(so, buf, cb + sizeof(DWORD), 0)) {
return 0;
}
} else {
if (send(so, buf, cb, 0)) {
return 0;
}
}
return 1;
}
void Socket_Server_IO::OnSend(bool ercode, P_server_struct nop) {
SOCKET n_so = nop->c_so;
delete[]nop->buf;
nop->buf = NULL;
delete nop;
nop = NULL;
if (ercode) {
closesockets(n_so);
onServerFunc(this, n_so, tcp_server_stop, 0, 0, m_cnum);
n_so = INVALID_SOCKET;
}
}
class Socket_Client_IO;
typedef struct client_struct {
OVERLAPPED op;
Socket_Client_IO *so;
int state;
char *buf;
DWORD slen;
DWORD cb;
DWORD bufSize;
DWORD bufOffset;
} S_client_struct, *P_client_struct;
class Socket_Client_IO {
public:
Socket_Client_IO(void);
~Socket_Client_IO(void);
int Init(char * host, unsigned short nPort, BOOL nIs, int time);
void OnConnect(bool ercode, P_client_struct op);
void OnClose(bool ercode, P_client_struct op);
void OnRecv(bool ercode, P_client_struct op);
int SoRecv(P_client_struct op);
int Close();
int doSend(char* buf, DWORD cb, int isok, char* outbuf, int outtime);
void OnSend(bool ercode, P_client_struct op);
SOCKET get_socket() {
return m_so;
}
public:
SOCKET m_so;
BOOL m_Is;
int m_isok;
char* m_buf;
};
Socket_Client_IO::Socket_Client_IO(void) {
m_so = INVALID_SOCKET;
}
Socket_Client_IO::~Socket_Client_IO(void) {
m_so = INVALID_SOCKET;
}
extern "C" __declspec(dllexport) int Socket_Client_IO::Init(char * host, unsigned short nPort, BOOL nIs, int time) {
m_so = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, WSA_FLAG_OVERLAPPED);
if (INVALID_SOCKET == m_so) {
return WSAGetLastError();
}
HANDLE t = CreateIoCompletionPort((HANDLE)m_so, hEvent_Client, 0, 0);
if (NULL == t) {
Close();
return GetLastError();
}
sockaddr_in in;
in.sin_family = AF_INET;
in.sin_addr.S_un.S_addr = 0;
in.sin_port = 0;
if (SOCKET_ERROR == bind(m_so, (SOCKADDR *)&in, sizeof (in))) {
Close();
return WSAGetLastError();
}
m_Is = nIs;
in.sin_family = AF_INET;
struct hostent *pHost;
pHost = gethostbyname(host);
memcpy(&in.sin_addr.S_un.S_addr, pHost->h_addr_list[0], pHost->h_length);
in.sin_addr.S_un.S_addr = inet_addr(inet_ntoa(in.sin_addr));
in.sin_port = htons(nPort);
unsigned long ul = 1;
ioctlsocket(m_so, FIONBIO, (unsigned long *)&ul);
connect(m_so, (sockaddr*)&in, sizeof(sockaddr));
struct timeval timeout ;
fd_set r;
FD_ZERO(&r);
FD_SET(m_so, &r);
timeout.tv_sec = time;
timeout.tv_usec = 0;
int ret = select(m_so, 0, &r, 0, &timeout);
if ( ret <= 0 ) {
Close();
return 1;
}
client_struct *op = new client_struct;
memset(op, 0, sizeof(client_struct));
op->so = this;
op->state = tcp_client_connt;
op->buf = NULL;
op->bufSize = 0;
op->bufOffset = 0;
PostQueuedCompletionStatus(hEvent_Client, 0, 0, (LPOVERLAPPED)op);
return 0;
}
extern "C" __declspec(dllexport) void Socket_Client_IO::OnConnect(bool ercode, P_client_struct op) {
setsockopt(m_so, SOL_SOCKET, 0x7010, NULL, 0);
onClientFunc(this, m_so, 1, NULL, 0);
if (ercode) {
OnClose(ercode, op);
return;
}
delete[]op->buf;
if (m_Is) {
op->buf = new char[sizeof(DWORD)];
op->bufSize = sizeof(DWORD);
} else {
op->buf = new char[tcp_len];
op->bufSize = tcp_len;
}
op->state = tcp_client_recv;
op->bufOffset = 0;
if (1 == SoRecv(op)) {
OnClose(ercode, op);
return;
}
}
void Socket_Client_IO::OnRecv(bool ercode, P_client_struct op) {
if (ercode) {
OnClose(ercode, op);
return;
}
if (m_Is) {
op->bufOffset += op->cb; //更新大小
if (op->bufOffset < op->bufSize) { //完整性检测
if (1 == SoRecv(op)) {
OnClose(ercode, op);
return ;
}
return;
}
DWORD size = *((DWORD*)(op->buf));
if (size > 65536000) { //数据错误
OnClose(ercode, op);
return;
}
if (op->bufOffset < DWORD(sizeof(DWORD)) + size) { //完整性检测
delete[] op->buf;
op->buf = new char[sizeof(DWORD) + size];
op->bufSize = sizeof(DWORD) + size;
op->bufOffset = sizeof(DWORD);
memcpy(op->buf, &size, sizeof(DWORD));
if (1 == SoRecv(op)) {
OnClose(ercode, op);
return;
}
return;
}
if (op->bufSize - sizeof(DWORD) > 0) {
if (m_isok > 0) {
memcpy(m_buf, op->buf + sizeof(DWORD), op->bufSize - sizeof(DWORD));
m_isok = 0;
}
onClientFunc(this, m_so, 2, op->buf + sizeof(DWORD), op->bufSize - sizeof(DWORD));
}
delete[] op->buf;
op->buf = new char[sizeof(DWORD)];
op->bufSize = sizeof(DWORD);
} else {
if (m_isok > 0) {
memcpy(m_buf, op->buf, op->cb);
}
onClientFunc(this, m_so, 2, op->buf, op->cb);
m_isok = 0;
}
op->bufOffset = 0;
if (1 == SoRecv(op)) {
OnClose(ercode, op);
return;
}
}
int Socket_Client_IO::SoRecv(P_client_struct op) {
op->so = this;
op->state = tcp_client_recv;
WSABUF wsabuf;
wsabuf.buf = op->buf + op->bufOffset;
wsabuf.len = op->bufSize - op->bufOffset;
DWORD Flg = 0;
if (WSARecv(m_so, &wsabuf, 1, &op->cb, &Flg, (LPWSAOVERLAPPED)op, NULL)) {
int ercode = WSAGetLastError();
if (ercode == WSAEFAULT) {
return 0;
} else if (ercode != WSA_IO_PENDING) {
return 1;
}
}
return 0;
}
void Socket_Client_IO::OnClose(bool ercode, P_client_struct op) {
delete[]op->buf;
op->buf = NULL;
delete op;
op = NULL;
onClientFunc(this, m_so, 3, NULL, 0);
Close();
}
int Socket_Client_IO::Close() {
closesockets(m_so);
m_so = INVALID_SOCKET;
return 0;
}
int Socket_Client_IO::doSend(char* buf, DWORD cb, int isok, char* outbuf, int outtime) {
if (cb > 65536000) {
return 0;
}
m_isok = isok;
m_buf = outbuf;
client_struct *op = new client_struct;
memset(op, 0, sizeof(client_struct));
op->so = this;
op->state = tcp_client_send;
WSABUF wsabuf;
if (m_Is) {
op->buf = new char[sizeof(DWORD) + cb];
op->bufSize = sizeof(DWORD) + cb;
wsabuf.buf = op->buf;
wsabuf.len = op->bufSize;
memcpy(wsabuf.buf, &cb, sizeof(DWORD));
memcpy(wsabuf.buf + sizeof(DWORD), buf, cb);
} else {
op->buf = buf;
op->bufSize = cb;
wsabuf.buf = op->buf;
wsabuf.len = op->bufSize;
}
if (WSASend(m_so, &wsabuf, 1, &op->cb, 0, (LPWSAOVERLAPPED)op, NULL)) {
int ercode = WSAGetLastError();
if (ercode != WSA_IO_PENDING) {
delete[]op->buf;
delete op;
return 1;
}
}
int ni = 0;
if (outtime <= 0) {
outtime = 2;
}
outtime = outtime * 1000;
while (1 == m_isok) {
ni++;
if (ni > outtime) {
m_isok = 0;
m_buf = NULL;
break;
}
Sleep(1);
}
return 0;
}
void Socket_Client_IO::OnSend(bool ercode, P_client_struct op) {
if (ercode) {
OnClose(ercode, op);
return;
}
if (m_Is) {
delete[]op->buf;
delete op;
}
}
unsigned __stdcall Worker_server(void* pParam) {
while (true) {
ULONG cb = 0;
ULONG_PTR key = 0;
server_struct* op = nullptr;
bool error = false;
if (!GetQueuedCompletionStatus(hEvent_Server, &cb, &key, (LPOVERLAPPED * )&op, INFINITE)) {
error = true;
}
Socket_Server_IO* so = op->so;
if (op->state == tcp_server_recv && cb <= 0) {
error = true;
}
op->cb = cb;
if (so->m_Close) {
so->OnSend(true, op);
continue;
}
switch (op->state) {
case tcp_server_connt:
so->ClientAccept(error, op);
break;
case tcp_server_recv:
so->RecvData(error, op);
break;
case tcp_server_send:
so->OnSend(error, op);
break;
default:
// Handle unexpected state
break;
}
}
_endthreadex(0);
return 0;
}
// Client worker function
unsigned __stdcall Worker_client(void* pParam) {
while (true) {
ULONG cb = 0;
ULONG_PTR key = 0;
client_struct* op = nullptr;
bool error = false;
if (!GetQueuedCompletionStatus(hEvent_Client, &cb, &key, (LPOVERLAPPED * )&op, INFINITE)) {
error = true;
}
Socket_Client_IO* so = op->so;
if (op->state == tcp_client_recv && cb <= 0) {
error = true;
}
op->cb = cb;
switch (op->state) {
case tcp_client_connt:
so->OnConnect(error, op);
break;
case tcp_client_recv:
so->OnRecv(error, op);
break;
case tcp_client_send:
so->OnSend(error, op);
break;
default:
// Handle unexpected state
break;
}
}
_endthreadex(0);
return 0;
}
extern "C" __declspec(dllexport) int __stdcall socket_init(onServer_ex nFun, onClient_ex cFun) {
WSAData wsa;
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
return WSAGetLastError();
}
onServerFunc = nFun;
onClientFunc = cFun;
hEvent_Server = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
if (hEvent_Server == NULL) {
return GetLastError();
}
hEvent_Client = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
if (hEvent_Client == NULL) {
CloseHandle(hEvent_Server);
return GetLastError();
}
SYSTEM_INFO info;
GetSystemInfo(&info);
g_cpu = info.dwNumberOfProcessors + 2;
if (g_cpu < 5) {
g_cpu = 5;
}
for (int i = 0; i < g_cpu; i++) {
HANDLE threadHandle = (HANDLE)_beginthreadex(NULL, 0, &Worker_server, NULL, 0, NULL);
if (threadHandle != NULL) {
CloseHandle(threadHandle);
}
threadHandle = (HANDLE)_beginthreadex(NULL, 0, &Worker_client, NULL, 0, NULL);
if (threadHandle != NULL) {
CloseHandle(threadHandle);
}
}
return 0;
}
extern "C" __declspec(dllexport) int __stdcall socket_server(char * host, unsigned short nPort, int nIs) {
Socket_Server_IO * dServer = new Socket_Server_IO;
if (0 != dServer->Init(host, nPort, nIs)) {
delete dServer;
dServer = NULL;
return 0;
}
return 0;
//return (int)dServer;
}
extern "C" __declspec(dllexport) int __stdcall socket_server_send(HANDLE sso, SOCKET so, char *buf, int len) {
return ((Socket_Server_IO*)sso)->doSend(so, buf, len);
}
extern "C" __declspec(dllexport) int __stdcall socket_server_sends(HANDLE sso, SOCKET so, char *buf, int len) {
return ((Socket_Server_IO*)sso)->doSend_sync(so, buf, len);
}
extern "C" __declspec(dllexport) int __stdcall socket_server_get_port(HANDLE so) {
return ((Socket_Server_IO*)so)->get_port();
}
char* __stdcall socket_server_get_ip(HANDLE so, SOCKET client_so) {
return ((Socket_Server_IO*)so)->get_ip(client_so);
}
SOCKET __stdcall socket_server_get_socket(HANDLE so) {
return ((Socket_Server_IO*)so)->get_socket();
}
extern "C" __declspec(dllexport) int __stdcall socket_server_close(SOCKET so) {
return closesockets(so);
}
extern "C" __declspec(dllexport) int __stdcall socket_server_stop(HANDLE so) {
if (IsBadReadPtr (so, 4) != 0) {
return 0;
}
Socket_Server_IO* dServer = ((Socket_Server_IO*)so);
dServer->Close();
delete dServer;
dServer = NULL;
return 0;
}
extern "C" __declspec(dllexport) int __stdcall socket_client(char * host, unsigned short nPort, BOOL nIs, int time) {
Socket_Client_IO * dClient = new Socket_Client_IO;
if (0 != dClient->Init(host, nPort, nIs, time)) {
delete dClient;
dClient = NULL;
return 0;
}
return 0;
//return (int)dClient;
}
extern "C" __declspec(dllexport) int __stdcall socket_client_send(HANDLE so, char *buf, int len, int isok, char* outbuf, int outtime) {
return ((Socket_Client_IO*)so)->doSend(buf, len, isok, outbuf, outtime);
}
extern "C" __declspec(dllexport) int __stdcall socket_client_close(HANDLE so) {
return ((Socket_Client_IO*)so)->Close();
}
extern "C" __declspec(dllexport) int __stdcall socket_client_get(HANDLE so) {
return ((Socket_Client_IO*)so)->get_socket();
}
//
//// Example implementation of the callback functions
//void __stdcall ServerCallback(HANDLE Server, SOCKET so, int type, char *buf, int len, int count) {
// //printf("ServerCallback invoked with type: %d, len: %d, count: %d\n", type, len, count);
//
// // 打印接收到的数据
// printf("Received data: ");
// for (int i = 0; i < len; ++i) {
// printf("%c", buf[i]);
// }
// printf("\n");
// if(type==1){
// char sendData[] = "ServerCallback:helloworld";
// socket_server_send(Server, so, sendData, strlen(sendData));
// }
//
//}
//
//
//void __stdcall ClientCallback(HANDLE Client, SOCKET so, int type, char *buf, int len) {
// //("ClientCallback invoked with type: %d, len: %d\n", type, len);
//
// // 打印接收到的数据
// printf("Received data: ");
// for (int i = 0; i < len; ++i) {
// printf("%c", buf[i]);
// }
// printf("\n");
// if(type==1){
// char sendData[] = "ClientCallback:helloworld";
// socket_client_send(Client, sendData, strlen(sendData), 0, 0, 0);
// }
//
//}
//
//int __stdcall main() {
// if (socket_init(ServerCallback, ClientCallback) == 0) {
// char hostname[] = "192.168.10.2";
// Socket_Server_IO * s = new Socket_Server_IO;
// printf("S %d \n", s->Init(hostname, 8800, 0));
// Socket_Client_IO * c = new Socket_Client_IO;
// printf("C %d \n", c->Init(hostname, 8800, 0, 30));
// Sleep(1000 * 60 * 60 * 30);
// }
// return 0;
//}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}