/* ========================================================================
Copyright (c) 2010, 
All rights reserved.

|文件名称|:CommSocket.h
|文件标识|:通信模块
|摘    要|: 封装了在套接字上的各种通信操作。

|当前版本|:
|作    者|:张涛
|完成日期|:

|取代版本|: 
|原 作 者|:张涛
|完成日期|:
======================================================================== 
*/

#pragma once
extern "C"    

    __declspec(dllexport) 
void __stdcall  CommSocketInit();
    __declspec(dllexport) 
void __stdcall  CommSocketDestroy();

    __declspec(dllexport) HANDLE __stdcall  CommSocketCreate( UINT nSocketPort , 
int nSocketType,LPCTSTR lpszSocketAddress );
    __declspec(dllexport) HANDLE __stdcall  CommSocketAccept(HANDLE hCommSocket,  LPSTR lpSockAddr,UINT 
*nPort);
    __declspec(dllexport) BOOLEAN  __stdcall  CommSocketConnect( HANDLE hCommSocket,LPCTSTR lpszHostAddress, UINT nHostPort );
    __declspec(dllexport) BOOLEAN   __stdcall  CommSocketListen(HANDLE hCommSocket, 
int nConnectionBacklog );
    __declspec(dllexport) 
int    __stdcall  CommSocketSend( HANDLE hCommSocket,const void* lpBuf, int nBufLen, int nFlags );
    __declspec(dllexport) 
int    __stdcall  CommSocketReceive(HANDLE hCommSocket, void* lpBuf, int nBufLen, int nFlags );
    __declspec(dllexport) 
int    __stdcall  CommSocketGetLastError();
    __declspec(dllexport) 
void   __stdcall  CommSocketClose(HANDLE hCommSocket);
}
;
//////////////////////////////////////////////////////////////////////////
//函数名:CommSocketInit
//功能:  初始化套接字,加载sock库
//参数:  无
//返回值:无
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////

//函数名: CommSocketDestroy
//功能:  卸载Socks库
//参数: 无
//返回值:无
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////

//函数名:CommSocketCreate
//功能:  创建一个指定类型和地址的套接字
//参数: 
//        [IN] UINT nSocketPort  // 端口号
//        [IN] int nSocketType //   套接字类型
//        [IN] LPCTSTR lpszSocketAddress //IP地址
//返回值:
//        创建成功返回一个指向套接字的句柄,失败返回INVALID_SOCKET_HANDLE
//引用函数:
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////

//函数名: CommSocketAccept
//功能:   接受远程连接
//参数:
//          [IN] HANDLE hCommSocket //指向本地监听套接字的句柄
//          [IN] LPSTR lpSockAddr   //客户端主机IP
//          [IN] UINT *nPort        //客户端进程PORT
//返回值:
//          接受成功返回一个指向专门用于IO处理的套接字句柄,
//          否则返回INVALID_SOCKET_HANDLE
//////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////

//函数名:CommSocketListen
//功能:    监听连接请求
//参数:
//          [IN] HANDLE hCommSocket //套接字句柄
//        [IN] int nConnectionBacklog //最大连接队列长度
//返回值:
//           BOOL 
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////

//函数名:CommSocketConnect
//功能:  请求连接到服务器
//参数:
//        [IN]  HANDLE hCommSocket //套接字句柄
//        [IN]  LPCTSTR lpszHostAddress//服务器IP
//        [IN]  UINT nHostPort//服务port
//返回值:
//          BOOL
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////

//函数名:CommSocketSend
//功能:  发送 数据
//参数:
//         [IN]    HANDLE hCommSocket //套接字句柄
//       [IN]   const void* lpBuf  //指向发送缓冲区的指针
//       [IN]   int nBufLen       // 发送数据的长度
//       [IN]   int nFlags        // 标准位
//返回值:
//       int,返回已发送的字节数
//////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////

//函数名:CommSocketReceive
//功能:  发送 数据
//参数:
//         [IN]    HANDLE hCommSocket //套接字句柄
//       [IN]   const void* lpBuf  //指向发送缓冲区的指针
//       [IN]   int nBufLen       // 发送数据的长度
//       [IN]   int nFlags        // 标准位
//返回值:
//       int,返回已接收的字节数
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////

//函数名:CommSocketGetLastError
//功能:  获取上次错误代码
//参数:
//返回值:int 错误代码值
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////

//函数名:CommSocketClose
//功能:  关闭套接字,回收套接字资源
//参数:
//         [IN] HANDLE hCommSocket //套接字句柄
//返回值:无
//////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////

//测试用例
//Sample
//////////////////////////////////////////////////////////////////////////
//BOOL Sample(void)
//{
//
//    CCommSocket testSocket;
//    BOOL bCreate = testSocket.Create(8888);
//    if (!bCreate)
//    {
//        return FALSE;
//    }
//
//    BOOL nListen= testSocket.Listen();
//    if (!nListen)
//    {
//        return FALSE;
//    }
//
//    CCommSocket ioSocket ;
//    char szIP[20] ={0};
//    UINT nPort = 0;
//    BOOL bAccept =testSocket.Accept(ioSocket,szIP,&nPort);//阻塞处
//    if (!bAccept)
//    {
//        return FALSE;
//    }
//
//    char szBuf[10]="test";
//    int nSend = ioSocket.Send(szBuf,sizeof(szBuf));
//    if (nSend < 0)
//    {
//        return FALSE;//BUG 2010-09-08
//    }
//
//    int nReceive = ioSocket.Receive(szBuf,sizeof(szBuf));
//    if (nReceive < 0)
//    {
//        return FALSE;
//    }
//
//    ioSocket.Close();
//    testSocket.Close();
//    return TRUE;
//
//}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// CommSocket.cpp : Defines the exported functions for the DLL application.
//

#include 
"stdafx.h"
#include 
"CommSocket.h"

#include 
<winsock2.h>
#pragma comment(lib,
"ws2_32.lib")

typedef 
struct _PSOCKET_HANDLE
{
    SOCKET m_socket;
}
 SOCKET_HANDLE,*PSOCKET_HANDLE;

//////////////////////////////////////////////////////////////////////////
//函数名: CommSocketInit
//功能:  加载Socks库
//参数: 无
//返回值:无
//////////////////////////////////////////////////////////////////////////
void __stdcall  CommSocketInit()
{
    WSACleanup( );

    WORD wVersionRequested;
    WSADATA wsaData;
    
int err;

    wVersionRequested 
= MAKEWORD( 22 );
    err 
= WSAStartup( wVersionRequested, &wsaData );
    
if ( err != 0 )
    
{    
        
return;
    }


    
if ( LOBYTE( wsaData.wVersion ) != 2 ||    HIBYTE( wsaData.wVersion ) != 2 ) 
    
{
        WSACleanup( );
        
return
    }


}


//////////////////////////////////////////////////////////////////////////
//函数名: CommSocketDestroy
//功能:  卸载Socks库
//参数: 无
//返回值:无
//////////////////////////////////////////////////////////////////////////
void __stdcall  CommSocketDestroy()
{
    WSACleanup( );
}


//////////////////////////////////////////////////////////////////////////
//函数名:CommSocketCreate
//功能:  创建一个指定类型和地址的套接字
//参数: 
//        [IN] UINT nSocketPort  // 端口号
//        [IN] int nSocketType //   套接字类型
//        [IN] LPCTSTR lpszSocketAddress //IP地址
//返回值:
//        创建成功返回一个指向套接字的句柄,失败返回INVALID_SOCKET_HANDLE
//引用函数:
//////////////////////////////////////////////////////////////////////////
HANDLE __stdcall  CommSocketCreate( UINT nSocketPort , int nSocketType,LPCTSTR lpszSocketAddress )
{
    PSOCKET_HANDLE pHandle 
= NULL;
    
do 
    
{
        SOCKET  sock 
= socket(AF_INET,nSocketType,IPPROTO_IP);
        
if(INVALID_SOCKET==sock)   
        
{
            
break;
        }


        sockaddr_in sa
={AF_INET};
        sa.sin_port
=htons(nSocketPort);
        sa.sin_addr.S_un.S_addr 
= htonl(ADDR_ANY);


        
int nRet = bind(sock,(sockaddr *)&sa,sizeof(sa));
        
int n = WSAGetLastError();

        
if (SOCKET_ERROR == nRet)
        
{
            
break;
        }

        pHandle 
= new SOCKET_HANDLE;

        pHandle
->m_socket = sock;

    }
 while (0);

    
return pHandle;

}


//////////////////////////////////////////////////////////////////////////
//函数名: CommSocketAccept
//功能:   接受远程连接
//参数:
//          [IN] HANDLE hCommSocket //指向本地监听套接字的句柄
//          [IN] LPSTR lpSockAddr   //客户端主机IP
//          [IN] UINT *nPort        //客户端进程PORT
//返回值:
//          接受成功返回一个指向专门用于IO处理的套接字句柄,
//          否则返回INVALID_SOCKET_HANDLE
//////////////////////////////////////////////////////////////////////////
HANDLE __stdcall  CommSocketAccept(HANDLE hCommSocket,  LPSTR lpSockAddr,UINT *nPort)
{
    PSOCKET_HANDLE pIOHandle 
= new SOCKET_HANDLE;
    PSOCKET_HANDLE pHandle 
= (PSOCKET_HANDLE)hCommSocket;
    sockaddr_in sa
={AF_INET};//客户套接字地址
    int nLen=sizeof(sa);

    pIOHandle
->m_socket = accept(pHandle->m_socket,(sockaddr*)&sa,&nLen);
    
if(INVALID_SOCKET==pIOHandle->m_socket)
    
{
        pIOHandle 
= NULL;
    }
    

    
if(lpSockAddr)
        strcpy(lpSockAddr,inet_ntoa(sa.sin_addr));
    
if(nPort)
        
*nPort=htons(sa.sin_port);

    
return pIOHandle;
}


//////////////////////////////////////////////////////////////////////////
//函数名:CommSocketConnect
//功能:  请求连接到服务器
//参数:
//        [IN]  HANDLE hCommSocket //套接字句柄
//        [IN]  LPCTSTR lpszHostAddress//服务器IP
//        [IN]  UINT nHostPort//服务port
//返回值:
//          BOOL
//////////////////////////////////////////////////////////////////////////
BOOLEAN  __stdcall  CommSocketConnect( HANDLE hCommSocket,LPCTSTR lpszHostAddress, UINT nHostPort )
{
    BOOLEAN bResult 
= FALSE;
    PSOCKET_HANDLE pHandle 
= (PSOCKET_HANDLE)hCommSocket;

    sockaddr_in sa 
={AF_INET};
    sa.sin_port 
= htons(nHostPort);
    sa.sin_addr.s_addr 
=inet_addr((PCSTR)lpszHostAddress);

    
int nlen = sizeof(sa);
    
int err=connect(pHandle->m_socket,(sockaddr*)&sa,sizeof(sa));
    
if(SOCKET_ERROR != err)
    
{
        bResult 
= TRUE;
    }

        
return bResult;

}

//////////////////////////////////////////////////////////////////////////
//函数名:CommSocketListen
//功能:    监听连接请求
//参数:
//          [IN] HANDLE hCommSocket //套接字句柄
//        [IN] int nConnectionBacklog //最大连接队列长度
//返回值:
//           BOOL 
//////////////////////////////////////////////////////////////////////////
BOOLEAN   __stdcall  CommSocketListen(HANDLE hCommSocket, int nConnectionBacklog )
{
    PSOCKET_HANDLE pHandle 
= (PSOCKET_HANDLE)hCommSocket;
    
return  !listen(pHandle->m_socket,nConnectionBacklog);
}



//////////////////////////////////////////////////////////////////////////
//函数名:CommSocketSend
//功能:  发送 数据
//参数:
//         [IN]    HANDLE hCommSocket //套接字句柄
//       [IN]   const void* lpBuf  //指向发送缓冲区的指针
//       [IN]   int nBufLen       // 发送数据的长度
//       [IN]   int nFlags        // 标准位
//返回值:
//       int,返回已发送的字节数
//////////////////////////////////////////////////////////////////////////
int    __stdcall  CommSocketSend( HANDLE hCommSocket,const void* lpBuf, int nBufLen, int nFlags )
{
    PSOCKET_HANDLE pHandle 
= (PSOCKET_HANDLE)hCommSocket;
    
return send(pHandle->m_socket, (LPSTR)lpBuf, nBufLen, nFlags);
}


//////////////////////////////////////////////////////////////////////////
//函数名:CommSocketReceive
//功能:  发送 数据
//参数:
//         [IN]    HANDLE hCommSocket //套接字句柄
//       [IN]   const void* lpBuf  //指向发送缓冲区的指针
//       [IN]   int nBufLen       // 发送数据的长度
//       [IN]   int nFlags        // 标准位
//返回值:
//       int,返回已接收的字节数
//////////////////////////////////////////////////////////////////////////
int    __stdcall  CommSocketReceive(HANDLE hCommSocket, void* lpBuf, int nBufLen, int nFlags )
{
    PSOCKET_HANDLE pHandle 
= (PSOCKET_HANDLE)hCommSocket;
    
return recv(pHandle->m_socket, (LPSTR)lpBuf, nBufLen, nFlags);
}



//////////////////////////////////////////////////////////////////////////
//函数名:CommSocketGetLastError
//功能:  获取上次错误代码
//参数:
//返回值:int 错误代码值
//////////////////////////////////////////////////////////////////////////
int    __stdcall  CommSocketGetLastError()
{
    
return WSAGetLastError();
}


//////////////////////////////////////////////////////////////////////////
//函数名:CommSocketClose
//功能:  关闭套接字,回收套接字资源
//参数:
//         [IN] HANDLE hCommSocket //套接字句柄
//返回值:无
//////////////////////////////////////////////////////////////////////////
void   __stdcall  CommSocketClose(HANDLE hCommSocket)
{
    PSOCKET_HANDLE pHandle 
= (PSOCKET_HANDLE)hCommSocket;
    closesocket(pHandle
->m_socket);
    pHandle
->m_socket = INVALID_SOCKET;
    delete pHandle;
    pHandle 
= NULL;
}