📄 tcpsocket.cpp
字号:
#include "StdAfx.h"
#include ".\tcpsocket.h"
CTcpSvrSocket::CTcpSvrSocket(int nListenPort,ITcpSocketUpper *pTSU)
{
m_pTSU = pTSU;
m_nListenPort = nListenPort;
m_hThread = NULL;
m_nThreadState = STOP;
int nErr;
WSADATA WsaData;
nErr = WSAStartup (0x0202, &WsaData);
if (nErr == SOCKET_ERROR)
{
//printf( "WSAStartup Failed\n");
return;
}
}
CTcpSvrSocket::~CTcpSvrSocket(void)
{
WSACleanup();
}
int WINAPI CTcpSvrSocket::SendData(char *pData,int len,int socketId)
{
if( socketId < 0 || NULL == pData || len < 0 )
return -1;
memset(pData+len,0,1);
return send(socketId,pData,len,0);
//LPWSAOVERLAPPEDEX lpOvlpEx;
//lpOvlpEx = (WSAOVERLAPPEDEX *) GlobalAlloc(GPTR,sizeof(WSAOVERLAPPEDEX));
//ZeroMemory(lpOvlpEx,sizeof(WSAOVERLAPPED));
//lpOvlpEx->WSABuf.len = len;
//lpOvlpEx->WSABuf.buf = pData;
//DWORD dwRecvBytes = 0,dwFlags = 0;
//
//if ( WSASend(socketId,&lpOvlpEx->WSABuf,1,&dwRecvBytes,dwFlags,(LPWSAOVERLAPPED)lpOvlpEx,NULL) == SOCKET_ERROR)
//{
// if ( WSAGetLastError() != WSA_IO_PENDING)
// {
// SafeClose(lpOvlpEx);
// }
//}
//GlobalFree(lpOvlpEx);
//return 0;
}
void CTcpSvrSocket::Start()
{
DWORD dwThreadID;
m_nThreadState = RUNNIG;
m_hThread = CreateThread(NULL,0,MainThread,(LPVOID)this,0,&dwThreadID);
if (m_hThread != NULL)
{
m_nThreadState = RUNNIG;
}
else
{
m_nThreadState = STOP;
}
}
void CTcpSvrSocket::Stop()
{
m_nThreadState = STOP;
}
DWORD WINAPI CTcpSvrSocket::ServerWorkerThread(LPVOID p)
{
CTcpSvrSocket *pTSS = (CTcpSvrSocket *)p;
HANDLE hCompletionPort = pTSS->m_hCompletionPort;
DWORD dwBytesTransferred = 0;
SOCKET hSocket;
LPWSAOVERLAPPEDEX lpOvlpEx;
int nErr;
sockaddr_in destaddr;
int len = sizeof(sockaddr_in);
while (1)
{
BOOL r = GetQueuedCompletionStatus(hCompletionPort,&dwBytesTransferred,(LPDWORD)&hSocket,(LPWSAOVERLAPPED *) &lpOvlpEx,INFINITE );
if (!r)
{
nErr = WSAGetLastError();
//printf("GetQueuedCompletionStatus = %d\n",nErr);
}
if (hSocket == 0 || lpOvlpEx == NULL)
break;
getsockname( hSocket,(sockaddr *)&destaddr,&len);
//printf("%d bytes transed...\n",dwBytesTransferred);
if (dwBytesTransferred == 0)
{
if (hSocket == lpOvlpEx->hSocket)
{
pTSS->SafeClose(lpOvlpEx);
//printf(" .....................%d..........closed & freed........\n",hSocket);
}
continue;
}
pTSS->m_pTSU->OnRecvData( lpOvlpEx->Buffer,dwBytesTransferred,destaddr,hSocket);
if (hSocket == lpOvlpEx->hSocket)
{
// todo ...
DWORD dwRecvBytes = 0,dwFlags = 0;
lpOvlpEx->WSABuf.len = DATA_BUFSIZE;
ZeroMemory(lpOvlpEx,sizeof(WSAOVERLAPPED));
if ( WSARecv(lpOvlpEx->hSocket,&lpOvlpEx->WSABuf,1,&dwRecvBytes,&dwFlags,(LPWSAOVERLAPPED)lpOvlpEx,NULL) == SOCKET_ERROR)
{
if ( WSAGetLastError() != WSA_IO_PENDING)
{
//printf("%d recv err = %d\n",lpOvlpEx->hSocket,WSAGetLastError());
if( NULL !=pTSS->m_pTSU )
pTSS->m_pTSU->OnClose( hSocket,destaddr );
pTSS->SafeClose(lpOvlpEx);
continue;
}
}
}
}
return 0;
}
DWORD WINAPI CTcpSvrSocket::MainThread(LPVOID pArgu)
{
CTcpSvrSocket *pTSS = (CTcpSvrSocket *)pArgu;
int nErr;
HANDLE hCompletionPort = CreateIoCompletionPort (
INVALID_HANDLE_VALUE,
NULL,
0,
0
);
if (!hCompletionPort)
{
//printf( "CompletionPort Create Failed\n");
return -1;
}
pTSS->m_hCompletionPort = hCompletionPort;
SYSTEM_INFO si;
GetSystemInfo(&si);
DWORD i = 0;
for ( i = 0 ; i < THREAD_MAXNUM; i++ )
{
HANDLE hThread;
DWORD dwThreadID;
hThread = CreateThread(NULL,0,ServerWorkerThread,pTSS,0,&dwThreadID);
//CloseHandle有无必要值得讨论,因为有时我们需要WaitForSingleObject(hThread,-1)来等待线程结束.
//
//CloseHandle(hThread);
}
SOCKADDR_IN localAddr;
SOCKET hListener;
hListener = WSASocket (AF_INET, SOCK_STREAM, 0,NULL,0,WSA_FLAG_OVERLAPPED);
if (hListener == INVALID_SOCKET)
{
//printf( "Socket Create Failed\n");
return -1;
}
//
// Bind our server to the agreed upon port number. See
// commdef.h for the actual port number.
//
ZeroMemory (&localAddr, sizeof (localAddr));
localAddr.sin_family = AF_INET;
localAddr.sin_port = htons (pTSS->m_nListenPort);
localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
nErr = bind (hListener, (PSOCKADDR) & localAddr, sizeof (localAddr));
if (nErr == SOCKET_ERROR)
{
//printf( "Socket Bind Failed\n");
if (WSAGetLastError () == WSAEADDRINUSE)
//printf( "The port number may already be in use.\n");
return -1;
}
nErr = listen (hListener, 5);
if (nErr == SOCKET_ERROR)
{
//printf( "Socket Listen Failed\n");
return -1;
}
SOCKET hAcceptSocket;
while (pTSS->m_nThreadState == RUNNIG)
{
hAcceptSocket = WSAAccept(hListener,NULL,NULL,NULL,0);
//线程绝大多数是等候在WSAAccept
if (pTSS->m_nThreadState != RUNNIG)
{
closesocket(hAcceptSocket);
break;
}
sockaddr_in destaddr;
int len = sizeof( destaddr );
getsockname( hAcceptSocket,(sockaddr *)&destaddr,&len);
pTSS->m_pTSU->OnConnect( destaddr, hAcceptSocket );
WSAOVERLAPPEDEX * pAcceptOvl = (WSAOVERLAPPEDEX *) GlobalAlloc(GPTR,sizeof(WSAOVERLAPPEDEX));
if (pAcceptOvl == NULL)
{
closesocket(hAcceptSocket);
//printf("accept %d error...\n",hAcceptSocket);
continue;
}
//printf("=======================================Accept= %d \n",hAcceptSocket);
//assert(pAccept);
pAcceptOvl->pPair = NULL;
pAcceptOvl->WSABuf.buf = pAcceptOvl->Buffer;
pAcceptOvl->WSABuf.len = DATA_BUFSIZE;
pAcceptOvl->hSocket = hAcceptSocket;
pAcceptOvl->pTSS = (LPVOID)pTSS;
CreateIoCompletionPort((HANDLE)hAcceptSocket,hCompletionPort,(DWORD)hAcceptSocket,0);
//pAccept->Recv();
DWORD dwRecvBytes = 0,dwFlags = 0;
if ( WSARecv(hAcceptSocket,&pAcceptOvl->WSABuf,1,&dwRecvBytes,&dwFlags,(LPWSAOVERLAPPED)pAcceptOvl,NULL) == SOCKET_ERROR)
{
if ( WSAGetLastError() != WSA_IO_PENDING)
{
//printf("%d accept recv err = %d",hAcceptSocket,WSAGetLastError());
}
}
}
//**************************
//如果一定要强制终止以获得请求的连接,打开下面的代码
/*
for( i = 0 ; i < THREAD_MAXNUM ; i++)
{
PostQueuedCompletionStatus(hCompletionPort,0,0,0);
}
*/
//*****************************
CloseHandle(hCompletionPort);
return 0;
}
void CTcpSvrSocket::SafeClose(LPWSAOVERLAPPEDEX lpOvlpEx)
{
sockaddr_in destaddr;
int len = sizeof( destaddr );
getsockname( lpOvlpEx->hSocket,(sockaddr *)&destaddr, &len);
this->m_pTSU->OnClose( lpOvlpEx->hSocket, destaddr );
if ( NULL != lpOvlpEx->hSocket )
{
closesocket(lpOvlpEx->hSocket); //close自己
GlobalFree(lpOvlpEx);//释放自己
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//client socket
CTcpCltSocket::CTcpCltSocket(int nListenPort,ITcpSocketUpper *pTSU)
{
m_pTSU = pTSU;
m_nListenPort = nListenPort;
m_hThread = NULL;
m_nThreadState = STOP;
m_socket = 0;
m_hCompletionPort = 0;
int nErr;
WSADATA WsaData;
nErr = WSAStartup (0x0202, &WsaData);
if (nErr == SOCKET_ERROR)
{
return;
}
}
CTcpCltSocket::~CTcpCltSocket(void)
{
WSACleanup();
}
int WINAPI CTcpCltSocket::SendData(char *pData,int len,int socketId)
{
if( NULL == pData || len < 0 || NULL == m_socket )
return -1;
memset(pData+len,0,1);
return send( this->m_socket, pData, len, 0);
}
bool CTcpCltSocket::Start(const char * ip, unsigned short port )
{
DWORD dwThreadID;
m_nThreadState = RUNNIG;
m_hCompletionPort = CreateIoCompletionPort (
INVALID_HANDLE_VALUE,
NULL,
0,
0
);
if (!m_hCompletionPort)
{
return false;
}
SYSTEM_INFO si;
GetSystemInfo(&si);
DWORD i = 0;
for ( i = 0 ; i < THREAD_MAXNUM; i++ )
{
HANDLE hThread;
DWORD dwThreadID;
hThread = CreateThread( NULL, 0, ServerWorkerThread, this, 0, &dwThreadID);
}
SOCKADDR_IN localAddr;
m_socket = WSASocket (AF_INET, SOCK_STREAM, 0,NULL,0,WSA_FLAG_OVERLAPPED);
if (m_socket == INVALID_SOCKET)
{
CloseHandle(m_hCompletionPort);
m_hCompletionPort = NULL;
return false;
}
ZeroMemory (&localAddr, sizeof (localAddr));
localAddr.sin_family = AF_INET;
localAddr.sin_port = htons (m_nListenPort);
localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
int nErr = bind (m_socket, (PSOCKADDR) & localAddr, sizeof (localAddr));
if (nErr == SOCKET_ERROR)
{
closesocket(m_socket);
CloseHandle(m_hCompletionPort);
m_hCompletionPort = NULL;
return false;
}
sockaddr_in sa;
sa.sin_family = AF_INET;
sa.sin_port = htons ( port );
sa.sin_addr.s_addr = inet_addr( ip ) ;
int salen = sizeof( sockaddr_in );
if( 0 > connect( m_socket,(sockaddr *)&sa , salen) )
{
closesocket(m_socket);
CloseHandle(m_hCompletionPort);
m_hCompletionPort = NULL;
}
m_pTSU->OnConnect( sa, m_socket);
WSAOVERLAPPEDEX * pAcceptOvl = (WSAOVERLAPPEDEX *) GlobalAlloc(GPTR,sizeof(WSAOVERLAPPEDEX));
if (pAcceptOvl == NULL)
{
closesocket(m_socket);
CloseHandle(m_hCompletionPort);
m_hCompletionPort = NULL;
return false;
}
pAcceptOvl->pPair = NULL;
pAcceptOvl->WSABuf.buf = pAcceptOvl->Buffer;
pAcceptOvl->WSABuf.len = DATA_BUFSIZE;
pAcceptOvl->hSocket = m_socket;
pAcceptOvl->pTSS = (LPVOID)this;
CreateIoCompletionPort((HANDLE)m_socket,m_hCompletionPort,(DWORD)m_socket,0);
//pAccept->Recv();
DWORD dwRecvBytes = 0,dwFlags = 0;
if ( WSARecv(m_socket,&pAcceptOvl->WSABuf,1,&dwRecvBytes,&dwFlags,(LPWSAOVERLAPPED)pAcceptOvl,NULL) == SOCKET_ERROR)
{
if ( WSAGetLastError() != WSA_IO_PENDING)
{
//printf("%d accept recv err = %d",hAcceptSocket,WSAGetLastError());
}
}
}
void CTcpCltSocket::Stop()
{
m_nThreadState = STOP;
::Sleep( 200 );
if( m_hCompletionPort )
CloseHandle( m_hCompletionPort );
}
DWORD WINAPI CTcpCltSocket::ServerWorkerThread(LPVOID p)
{
CTcpCltSocket *pTSS = (CTcpCltSocket *)p;
HANDLE hCompletionPort = pTSS->m_hCompletionPort;
DWORD dwBytesTransferred = 0;
SOCKET hSocket;
LPWSAOVERLAPPEDEX lpOvlpEx;
int nErr;
sockaddr_in destaddr;
int len = sizeof(sockaddr_in);
while (1)
{
BOOL r = GetQueuedCompletionStatus(hCompletionPort,&dwBytesTransferred,(LPDWORD)&hSocket,(LPWSAOVERLAPPED *) &lpOvlpEx,INFINITE );
if (!r)
{
nErr = WSAGetLastError();
//printf("GetQueuedCompletionStatus = %d\n",nErr);
}
if (hSocket == 0 || lpOvlpEx == NULL)
break;
getsockname( hSocket,(sockaddr *)&destaddr,&len);
//printf("%d bytes transed...\n",dwBytesTransferred);
if (dwBytesTransferred == 0)
{
if (hSocket == lpOvlpEx->hSocket)
{
pTSS->SafeClose(lpOvlpEx);
//printf(" .....................%d..........closed & freed........\n",hSocket);
}
continue;
}
pTSS->m_pTSU->OnRecvData( lpOvlpEx->Buffer,dwBytesTransferred,destaddr,hSocket);
if (hSocket == lpOvlpEx->hSocket)
{
// todo ...
DWORD dwRecvBytes = 0,dwFlags = 0;
lpOvlpEx->WSABuf.len = DATA_BUFSIZE;
ZeroMemory(lpOvlpEx,sizeof(WSAOVERLAPPED));
if ( WSARecv(lpOvlpEx->hSocket,&lpOvlpEx->WSABuf,1,&dwRecvBytes,&dwFlags,(LPWSAOVERLAPPED)lpOvlpEx,NULL) == SOCKET_ERROR)
{
if ( WSAGetLastError() != WSA_IO_PENDING)
{
//printf("%d recv err = %d\n",lpOvlpEx->hSocket,WSAGetLastError());
if( NULL !=pTSS->m_pTSU )
pTSS->m_pTSU->OnClose( hSocket,destaddr );
pTSS->SafeClose(lpOvlpEx);
continue;
}
}
}
}
return 0;
}
void CTcpCltSocket::SafeClose(LPWSAOVERLAPPEDEX lpOvlpEx)
{
sockaddr_in destaddr;
int len = sizeof( destaddr );
getsockname( lpOvlpEx->hSocket,(sockaddr *)&destaddr, &len);
this->m_pTSU->OnClose( lpOvlpEx->hSocket, destaddr );
if ( NULL != lpOvlpEx->hSocket )
{
closesocket(lpOvlpEx->hSocket); //close自己
GlobalFree(lpOvlpEx);//释放自己
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -