TcpSocket.h
#ifndef __CTCPSOCKET_H__
#define __CTCPSOCKET_H__
#include <WinSock2.h>
enum OVER_TYPE { RECV_OVERLAPPED, SEND_OVERLAPPED, BOTH_OVERLAPPED };
enum OPER_TYPE { RECV_POSTED, SEND_POSTED };
enum SEND_ERROR_TYPE { SUCCESS ,OVER_BUFFER_ERROR , SOCKET_INVALID_ERROR, NULL_BUFFER_ERROR };
#define BUFFER_SIZE 4096
class CTCPSocket
{
protected:
SOCKET m_socket;
SOCKADDR_IN m_sockAddr;
unsigned long m_ulIpAddr;
char m_szIP[ 16 ];
//重叠结构
WSAOVERLAPPED m_RecvOverLapped;
WSAOVERLAPPED m_SendOverLapped;
//数据缓冲区,分别用来接收和发送数据时使用
WSABUF m_wsaRecvBuf;
WSABUF m_wsaSendBuf;
char m_szRecvBuf[ BUFFER_SIZE ];
char m_szSendBuf[ BUFFER_SIZE ];
//操作类型表示
OPER_TYPE m_dwOperType; // RECV_POSTED, SEND_POSTED ;
INT m_nNetErr;
protected:
VOID InitOverLapped( OVER_TYPE Type );
public:
// 参数1: 对象池; 参数2: 接收缓冲区队列
CTCPSocket( VOID );
virtual ~CTCPSocket( VOID );
BOOL Connect( char *pDestAddr, int nPort );
VOID InitSocket( SOCKET s, SOCKADDR_IN* pSockAddr );
VOID ReleaseSocket( VOID );
VOID RecvData( VOID );
// 发送原始数据时使用
BOOL SendData( char* pBuf, DWORD dwLength );
INT GetNetErrCode( VOID ) { return m_nNetErr; }
OPER_TYPE GetOperType( VOID ) { return m_dwOperType; }
WSAOVERLAPPED* GetRecvOverlapped( VOID ) { return &m_RecvOverLapped; }
WSAOVERLAPPED* GetSendOverlapped( VOID ) { return &m_SendOverLapped; }
unsigned long GetIPAddr( VOID ) { return m_ulIpAddr; }
char* GetIP( VOID ) { return m_szIP; }
SOCKET GetSocket( VOID ) { return m_socket; }
SOCKADDR_IN* GetSockAddr( VOID ) { return &m_sockAddr; }
};
#endif
TcpSocket.cpp
#include "TcpSocket.h"
#include <assert.h>
#include <stdio.h>
CTCPSocket::CTCPSocket( VOID )
{
m_socket = INVALID_SOCKET;
m_nNetErr = 0;
m_ulIpAddr = 0;
memset( m_szIP, 0, BUFFER_SIZE );
}
CTCPSocket::~CTCPSocket( VOID )
{
if ( INVALID_SOCKET == m_socket )
{
return;
}
ReleaseSocket();
}
VOID CTCPSocket::InitOverLapped( OVER_TYPE Type )
{
if( RECV_OVERLAPPED == Type )
{
ZeroMemory( &m_RecvOverLapped,sizeof( WSAOVERLAPPED ) );
}
else if( SEND_OVERLAPPED == Type )
{
ZeroMemory( &m_SendOverLapped,sizeof( WSAOVERLAPPED ) );
}
else if( BOTH_OVERLAPPED == Type )
{
ZeroMemory( &m_RecvOverLapped,sizeof( WSAOVERLAPPED ) );
ZeroMemory( &m_SendOverLapped,sizeof( WSAOVERLAPPED ) );
}
}
VOID CTCPSocket::RecvData( VOID )
{
if( INVALID_SOCKET == m_socket )
{
return;
}
InitOverLapped( RECV_OVERLAPPED );
m_dwOperType = RECV_POSTED;
m_wsaRecvBuf.buf = m_szRecvBuf;
m_wsaRecvBuf.len = BUFFER_SIZE;
unsigned long Flag=0;
DWORD RecvByte;
::WSARecv( m_socket,
&( m_wsaRecvBuf ),
1,
&RecvByte,
&Flag,
&( m_RecvOverLapped ),
NULL);
}
BOOL CTCPSocket::SendData( char* pBuf, DWORD dwLength )
{
if( INVALID_SOCKET == m_socket )
{
printf( "Error, file: %s, line: %d /n", __FILE__, __LINE__ );
m_nNetErr = SOCKET_INVALID_ERROR;
return FALSE;
}
if( NULL == pBuf )
{
printf( "Error, file: %s, line: %d /n", __FILE__, __LINE__ );
m_nNetErr = NULL_BUFFER_ERROR;
return FALSE;
}
if(dwLength > BUFFER_SIZE )
{
printf( "Error, file: %s, line: %d /n", __FILE__, __LINE__ );
m_nNetErr = OVER_BUFFER_ERROR;
return FALSE;
}
//准备缓冲
unsigned long Flag=0;
DWORD SendByte;
InitOverLapped( SEND_OVERLAPPED );
memcpy( m_szSendBuf, pBuf, dwLength );
m_wsaSendBuf.buf = m_szSendBuf;
m_wsaSendBuf.len = dwLength;
m_dwOperType = SEND_POSTED;
int nRet = ::WSASend( m_socket,
&( m_wsaSendBuf ),
1,
&SendByte,
Flag,
&( m_SendOverLapped ),
NULL );
int nErr = ::WSAGetLastError();
if( ( SOCKET_ERROR == nRet ) && ( WSA_IO_PENDING != nErr ) )
{
printf( "WSASend error: %d /n", nErr );
m_nNetErr = nErr;
return FALSE;
}
else
{
return TRUE;
}
}
VOID CTCPSocket::InitSocket( SOCKET s, SOCKADDR_IN* pSockAddr )
{
m_socket = s;
memcpy( &m_sockAddr, pSockAddr, sizeof( *pSockAddr ) );
m_ulIpAddr = m_sockAddr.sin_addr.S_un.S_addr;
strcpy( m_szIP, inet_ntoa( m_sockAddr.sin_addr ) );
}
VOID CTCPSocket::ReleaseSocket( VOID )
{
if ( INVALID_SOCKET != m_socket )
{
return;
}
LINGER LingerStruct;
LingerStruct.l_onoff=1;
LingerStruct.l_linger=0;
setsockopt( m_socket, SOL_SOCKET, SO_LINGER, ( char*)&LingerStruct, sizeof( LingerStruct ) );
shutdown( m_socket, SD_BOTH );
closesocket( m_socket );
m_socket = INVALID_SOCKET;
m_nNetErr = 0;
m_ulIpAddr = 0;
memset( m_szIP, 0, BUFFER_SIZE );
memset( &m_sockAddr, 0, sizeof( SOCKADDR_IN ) );
}
BOOL CTCPSocket::Connect( char *pDestAddr, int nPort )
{
//服务器地址
//m_socket = socket( AF_INET ,SOCK_STREAM , 0 ) ;
m_socket = WSASocket( AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0 ,WSA_FLAG_OVERLAPPED );
m_sockAddr.sin_addr.S_un.S_addr = inet_addr( pDestAddr ) ;
m_sockAddr.sin_family = AF_INET ;
m_sockAddr.sin_port = htons( nPort ) ;
int nRet = ::WSAConnect( m_socket, ( SOCKADDR* )&m_sockAddr, sizeof( SOCKADDR ),0, 0, 0, 0 );
if ( SOCKET_ERROR == nRet )
{
m_nNetErr = ::WSAGetLastError();
return FALSE;
}
return TRUE;
}