main函数和工作线程文件
#include "stdafx.h"
#include
#include "CDSocket.h"
#pragma comment(lib, "ws2_32.lib")
struct PER_HANDLE_DATA
{
SOCKET s;
sockaddr_in addr;
PER_HANDLE_DATA (SOCKET s0, sockaddr_in addr0) : s(s0), addr(addr0){}
};
struct PER_IO_DATA
{
WSAOVERLAPPED ol;
char buf[BUFFER_SIZE];
int nOperation;
PER_IO_DATA (int op)
{
ZeroMemory(this, sizeof(PER_IO_DATA));
nOperation = op;
}
};
DWORD WINAPI ServerThread(LPVOID lpParam);
SockInit si;
int _tmain(int argc, _TCHAR* argv[])
{
//创建完成端口
HANDLE hIocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
//创建工作线程
HANDLE hThread = CreateThread(NULL, 0, ServerThread, (LPVOID)hIocp, 0, 0);
//创建socket
CDSocket sListen;
sListen.Create();
//绑定
sListen.Bind(4567);
//监听
sListen.Listen();
while (true)
{
//接受连接
sockaddr_in remoteAddr;
CDSocket sRemote = sListen.Accept((sockaddr*)&remoteAddr);
printf("接受ip=%s port=%d的连接\n", inet_ntoa(remoteAddr.sin_addr), ntohs(remoteAddr.sin_port));
//连接socket关联完成端口
PER_HANDLE_DATA* pPerHandle = new PER_HANDLE_DATA(sRemote, remoteAddr);
CreateIoCompletionPort((HANDLE)pPerHandle->s, hIocp, (ULONG_PTR)pPerHandle, 0);
//投递异步接收请求
/* PER_IO_DATA* pPerIO = (PER_IO_DATA *)::GlobalAlloc(GPTR, sizeof(PER_IO_DATA));
pPerIO->nOperation = OP_READ;
OVERLAPPED结构必须为0 否则一定失败 tmd老子调了一下午
*/
PER_IO_DATA* pPerIO = new PER_IO_DATA(OP_READ);
sRemote.Recv(pPerIO->buf, BUFFER_SIZE, NULL, (LPWSAOVERLAPPED)pPerIO);
}
return 0;
}
DWORD WINAPI ServerThread(LPVOID lpParam)
{
HANDLE hIocp = (HANDLE)lpParam;
DWORD dwTrans;
PER_HANDLE_DATA* pPerHandle = NULL;
PER_IO_DATA* pPerIO = NULL;
while (true)
{
BOOL bOK = GetQueuedCompletionStatus(hIocp, &dwTrans, (PULONG_PTR)&pPerHandle, (LPOVERLAPPED*)&pPerIO, WSA_INFINITE);
if (!bOK)
{
closesocket(pPerHandle->s);
delete pPerHandle;
delete pPerIO;
continue;
}
if (dwTrans == 0 && (pPerIO->nOperation == OP_READ || pPerIO->nOperation == OP_WRITE))
{
closesocket(pPerHandle->s);
delete pPerHandle;
delete pPerIO;
continue;
}
switch (pPerIO->nOperation)
{
case OP_READ:
{
pPerIO->buf[dwTrans] = '\0';
printf(pPerIO->buf);
/*WSABUF buf;
buf.buf = pPerIO->buf;
buf.len = BUFFER_SIZE;
pPerIO->nOperation = OP_READ;
DWORD nFlags = 0;
WSARecv(pPerHandle->s, &buf, 1, &dwTrans, &nFlags, lpOverLapped, NULL);*/
CDSocket sClient(pPerHandle->s);
//sClient.Recv(pPerIO->buf, BUFFER_SIZE, NULL, (LPWSAOVERLAPPED)pPerIO);
sClient.Send(pPerIO->buf, strlen(pPerIO->buf));
}
case OP_WRITE:
{
}
case OP_ACCEPT:
{
}
default:
break;
}
}
return 0;
}
需要的两个socket封装类
//SockInit是初始化socket环境的类,定义一个此类的全局变量即可
//socket的简单封装CDSocket.h
#include
#define BUFFER_SIZE 1024
#define OP_READ 1
#define OP_WRITE 2
#define OP_ACCEPT 3
struct SockInit
{
SockInit()
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
}
~SockInit()
{
WSACleanup();
}
};
class CDSocket
{
public:
CDSocket(SOCKET hSocket = NULL) :m_hSocket(hSocket)
{}
~CDSocket()
{
if (m_hSocket != NULL)
{
closesocket(m_hSocket);
}
}
CDSocket& operator=(const CDSocket& rhs)
{
if (m_hSocket != NULL)
{
closesocket(m_hSocket);
}
m_hSocket = rhs.m_hSocket;
return *this;
}
CDSocket& operator=(const SOCKET& hSocket)
{
if (m_hSocket != NULL)
{
closesocket(m_hSocket);
}
m_hSocket = hSocket;
return *this;
}
bool Create()
{
m_hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == m_hSocket)
{
m_hSocket = NULL;
return false;
}
return true;
}
int Bind(short nPort)
{
sockaddr_in localAddr;
localAddr.sin_family = AF_INET;
localAddr.sin_port = ntohs(nPort);
localAddr.sin_addr.S_un.S_addr = INADDR_ANY;
return bind(m_hSocket, (sockaddr*)&localAddr, sizeof(localAddr));
}
int Listen(int backend = 10)
{
return listen(m_hSocket, backend);
}
CDSocket Accept(sockaddr* remoteAddr)
{
int nRemoteAddrLen = sizeof(sockaddr);
return CDSocket(accept(m_hSocket, remoteAddr, &nRemoteAddrLen));
}
int Connect(const char* szIp, short nPort)
{
sockaddr_in remoteAddr;
remoteAddr.sin_family = AF_INET;
remoteAddr.sin_port = ntohs(nPort);
remoteAddr.sin_addr.S_un.S_addr = inet_addr(szIp);
return connect(m_hSocket, (sockaddr*)&remoteAddr, sizeof(remoteAddr));
}
int Send(char* szBuf, int len)
{
return send(m_hSocket, szBuf, len, 0);
}
int Recv(char* szBuf, int nBufSize, LPDWORD lpNumberOfBytesRecvd, LPWSAOVERLAPPED lpOverLapped)
{
WSABUF buf;
buf.buf = szBuf;
buf.len = nBufSize;
DWORD dwFlags = 0;
return WSARecv(m_hSocket, &buf, 1, lpNumberOfBytesRecvd, &dwFlags, lpOverLapped, NULL);
}
operator SOCKET()
{
return m_hSocket;
}
void Attach(SOCKET hSocket)
{
if (m_hSocket != NULL)
{
closesocket(m_hSocket);
}
m_hSocket = hSocket;
}
private:
SOCKET m_hSocket;
};