📄 clientsocket.cpp
字号:
/*******************************************************************************
* (C) Copyright 2008 Giant Electronics LTD
*
* These computer program listings and specifications are the property of Giant
* Electronics LTD and shall not be reproduced or copied or used in whole or in
* part without written permission from Giant Electronics LTD .
*
* Project: IViewer
* File Name: ClientSocket.h
* Programer(s): Ben Zhan
* Created: 20080729
* Description: implementation of encapsulating Wince Socket APIs
* This class encapsulates the wince Socket API.
*******************************************************************************/
#include "stdafx.h"
#include "ClientSocket.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CClientSocket::CClientSocket()
{
m_hSocket = NULL;
//m_hAysnEvent
m_dwConnectTimeout = 10000; //默认非阻塞连接超时为10秒
m_dwRecvTimeout = 6000;
m_dwSendTimeout = 6000;
m_lEventSelected = 0;
m_hWnd = NULL;
m_bBlock = TRUE;
}
BOOL CClientSocket::SocketInit()
{
WSADATA wsData;
int nResult=WSAStartup(MAKEWORD(1,1),&wsData);
if(nResult !=0)
{
return FALSE ;
}
return TRUE ;
}
CClientSocket::~CClientSocket()
{
Disconnect();
}
void CClientSocket::Disconnect(void)
{
try
{
if (m_hSocket)
{
// Terminate receiving and sending thread if necessary
closesocket(m_hSocket);
m_hSocket = NULL;
}
}
catch(...)
{
LUIS_TRACE(L"CClientSocket::Disconnect");
}
}
// Attach a connected sockt to this object
bool CClientSocket::Attach(SOCKET inSock)
{
if (m_hSocket != NULL)
return false;
m_hSocket = inSock;
return true;
}
SOCKET CClientSocket::Detach(void)
{
SOCKET hSock = m_hSocket;
m_hSocket = NULL;
return hSock;
}
int CClientSocket::recv(char * outBuf , int nlen)
{
return ::recv(m_hSocket, outBuf, nlen, 0);
}
int CClientSocket::Receive(char * outBuf, int inLen)
{
if(!m_hSocket)
return E_SOCKET_FAIL;
// Check socket for readability
TIMEVAL tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
fd_set rfds;
while(true)
{
FD_ZERO(&rfds);
FD_SET(m_hSocket, &rfds);
if (select(1, &rfds, NULL, NULL,&tv))
{
int nCount = inLen;
int lenret = 0;
char * pBuf = outBuf;
do
{
lenret = ::recv(m_hSocket, pBuf, nCount, 0);
if (lenret == SOCKET_ERROR)
{
return E_SOCKET_FAIL;
}
else if (lenret == 0)
{
// Indicate the socket disconnected
return E_SOCKET_CLOSE;
}
nCount -= lenret;
pBuf += lenret;
if (nCount > 0)
Sleep(20);
} while (nCount > 0);
return S_SOCKET_OK;
}
else
{
// The socket not ready to read
continue;
}
}
return E_SOCKET_FAIL;
}
int CClientSocket::Send(const char * pData, int inLen)
{
if (!m_hSocket || !pData)
return E_SOCKET_FAIL;
int nret = 0;
int nCount = inLen;
do
{
if (WaitForSocket(WAIT_SEND,20) != S_SOCKET_OK)
return E_SOCKET_FAIL;
nret = send(m_hSocket, pData, nCount, 0);
if (nret == SOCKET_ERROR)
{
return E_SOCKET_FAIL;
}
nCount -= nret;
pData += nret;
}
while (nCount > 0);
return S_SOCKET_OK;
return E_SOCKET_FAIL;
}
//modified by Ben 2009-01-05 support cancel event
//Connect to the remote socket
bool CClientSocket::Connect(LPCSTR lpszTarget, int iPort, HANDLE hCancelEvent/*=NULL*/)
{
Disconnect();
// Create a new socket to connection
m_hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (m_hSocket == INVALID_SOCKET)
{
m_hSocket = NULL;
return false;
}
// Resolve hostname
DWORD addr = inet_addr(lpszTarget);
if (addr == INADDR_NONE)
{
struct hostent *he = NULL ;
int ntrytimes = 0 ;
he = gethostbyname(lpszTarget);
while (he == NULL && ntrytimes < 2)
{
ntrytimes ++;
he = gethostbyname(lpszTarget);
}
if (he == NULL)
{
LUIS_TRACE(L"Socket couldn't look up host\n");
closesocket(m_hSocket);
m_hSocket = NULL;
return false;
}
addr = *(DWORD *)(he->h_addr_list[0]);
}
if (m_bBlock != TRUE) //设置非阻塞方式连接
{
ULONG temp = 1;
UINT32 ret = 0;
ret = ::ioctlsocket(m_hSocket, FIONBIO, &temp);
}
/*
if( m_lEventSelected != 0 && m_hWnd!=NULL )
{
int nRet = ::WSAAsyncSelect (m_hSocket, m_hWnd, WM_CLIENTSOCKET, m_lEventSelected) ;
if( nRet==SOCKET_ERROR )
{
DWORD dwError = WSAGetLastError();
}
}
*/
BOOL sopt = TRUE;
setsockopt(m_hSocket, IPPROTO_TCP, TCP_NODELAY, (char *)&sopt, sizeof(BOOL));
setsockopt(m_hSocket, SOL_SOCKET, SO_DONTLINGER, (char *)&sopt, sizeof(BOOL));
//set Recv and Send time out
//设置发送超时
/*
available in Microsoft implementation of Windows Sockets 2
if(::setsockopt(m_hSocket,SOL_SOCKET,SO_SNDTIMEO,(char *)&m_dwSendTimeout,sizeof(m_dwSendTimeout))==SOCKET_ERROR)
{
DWORD dwError = WSAGetLastError();
return false;
}
//设置接收超时
if(::setsockopt(m_hSocket,SOL_SOCKET,SO_RCVTIMEO,(char *)&m_dwRecvTimeout,sizeof(m_dwSendTimeout))==SOCKET_ERROR)
{
DWORD dwError = WSAGetLastError();
return false;
}
*/
// Create socket address
SOCKADDR_IN saddr;
memset(&saddr, 0, sizeof(SOCKADDR_IN));
saddr.sin_addr.S_un.S_addr = addr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons((WORD)iPort);
// Connect to the remote host
int nRet ;
nRet = connect(m_hSocket, (SOCKADDR *)&saddr, sizeof(SOCKADDR_IN));
if (nRet == SOCKET_ERROR)
{
DWORD dwError = WSAGetLastError();
if (m_bBlock == FALSE && dwError == WSAEWOULDBLOCK)
{
nRet = WaitForSocket(WAIT_CONNECT,m_dwConnectTimeout/1000,hCancelEvent);
if (nRet == S_SOCKET_OK)
{
//连接成功,设回阻塞模式方便处理接收与发送,否则一般的recv send很难控制
ULONG temp = 0;
UINT32 ret = 0;
ret = ::ioctlsocket(m_hSocket, FIONBIO, &temp);
return true;
}
}
closesocket(m_hSocket);
m_hSocket = NULL;
return false;
}
else if (nRet != 0)
{
closesocket(m_hSocket);
m_hSocket = NULL;
return false;
}
return true;
}
int CClientSocket::WaitForSocket(WAIT_TYPE waitType,int nSecs,HANDLE hCancelEvent)
{
int nRet = E_SOCKET_TIMEOUT;
int nTryTimes = 0;
TIMEVAL tm;
tm.tv_sec = 1;
tm.tv_usec = 0;
FD_SET fds;
if (!hCancelEvent)
{//no cancel event then waitting one times
tm.tv_sec = nSecs;
nSecs = 1;
}
else
tm.tv_sec = 1;
while(nTryTimes < nSecs)
{
nTryTimes ++;
if (hCancelEvent && WaitForSingleObject(hCancelEvent,0) == WAIT_OBJECT_0)
{
nRet = E_SOCKET_CANCEL;
break;
}
FD_ZERO(&fds);
FD_SET(m_hSocket, &fds);
int nRes;
switch(waitType)
{
case WAIT_CONNECT:
nRes = ::select(0, 0, &fds, NULL, &tm);
break;
case WAIT_SEND:
nRes = ::select(0, NULL, &fds, NULL, &tm);
break;
case WAIT_RECV:
nRes = ::select(0, &fds, NULL, NULL, &tm);
break;
}
if (nRes == SOCKET_ERROR)
{
DWORD dwRes=WSAGetLastError();
TRACE(L"\nselect recv status errorcode=%d\n",dwRes);
}
else if (nRes > 0)
{
nRet = S_SOCKET_OK;
break;
}
}
return nRet;
}
//设置阻塞状态,true为阻塞
void CClientSocket::SetBlock(BOOL bBlock)
{
if( m_bBlock == bBlock )
return ;
m_bBlock = bBlock ;
}
void CClientSocket::AsyncSelect(long lEvent , HWND hWnd)
{
ASSERT (hWnd) ;
m_lEventSelected = lEvent ;
m_hWnd = hWnd ;
}
void CClientSocket::SetRecvTimeout(DWORD dwTime/*=10000 默认10秒*/)
{
m_dwRecvTimeout = dwTime;
}
void CClientSocket::SetSendTimeout(DWORD dwTime/*=10000 默认10秒*/)
{
m_dwSendTimeout = dwTime;
}
void CClientSocket::SetConnectTimeout(DWORD dwTime/*=10000 默认10秒*/)
{
m_dwConnectTimeout = dwTime;
m_bBlock = FALSE ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -