📄 tcpsocket.cpp
字号:
int i;
BOOL bIP;
int nNumber;
struct hostent *ip;
DWORD dwIP;
char buf[MAXGETHOSTSTRUCT];
HANDLE hResolve;
LPCTSTR lpHost = (LPCTSTR)szHost;
int nResult;
//名称无效
if( lpHost == NULL ) return FALSE;
//首先假设输入地址为IP地址
//计算长度
iLen = strlen(lpHost);
if( iLen == 0 ) return FALSE;
//判断是否为点分的IP
bIP = TRUE;
nNumber = 0; //计算输入的地址中点的个数
for(i=0;i<iLen;i++)
{
if( (lpHost[i]<'0')||(lpHost[i]>'9') )
{
/* 判断是否为0-9字符和.符号 */
/* lpHost是域名 */
if( lpHost[i] == '.' ) nNumber++;
else
{
bIP = FALSE;
break;
}
}
}
// 输入是IP地址,不是域名
if( bIP == TRUE )
{
//如果'.'符号不是3个,肯定有问题,这是针对IPv4
if( nNumber != 3 ) return FALSE;
else
{
dwIP = inet_addr( lpHost );
// IP地址有误
if( dwIP == INADDR_NONE ) return FALSE;
ipServer = *((LPIN_ADDR)&dwIP);
return TRUE;
}
}
////////////////////////////////////////////
// 解析
/////////////////////
//异步操作
hResolve = WSAAsyncGetHostByName(
m_hMainWnd, //handle
SOCKET_THREAD_RESOLVE, //message
lpHost, //source
buf, //result
MAXGETHOSTSTRUCT );
if( hResolve == 0 ) return FALSE;
//开始等待窗口处理消息
// 注意:
// 如果用户选择取消,则m_bCancelJob = TRUE
m_bCancelJob = FALSE;
ResetEvent( m_hWaitEvent );
nResult = WaitForSingleObject( m_hWaitEvent, confChat.nWaitTime*2000);
ASSERT( nResult != WAIT_TIMEOUT );
if( nResult == WAIT_TIMEOUT )
{
m_bState = SOCKET_ERROR_TIMEOUT;
return FALSE;
}
// 如果是取消解析
if( m_bCancelJob == TRUE )
{
WSACancelAsyncRequest( hResolve );
return FALSE;
}
// 解析成功
ip = (struct hostent *)buf;
// 如果解析的地址不是IP地址
if( ip->h_length != sizeof(IN_ADDR) )
{
return FALSE;
}
memcpy( (void *)&ipServer, (void *)(ip->h_addr_list[0]) , ip->h_length );
return TRUE;
}
void CTCPSocket::Stop()
{
SetEvent( m_hWaitEvent );
m_bCancelJob = TRUE;
}
void CTCPSocket::StopWait()
{
SetEvent( m_hWaitEvent );
m_bCancelJob = FALSE;
}
SOCKET CTCPSocket::GetSocket()
{
return m_TCP_s;
}
BOOL CTCPSocket::CreateTransfer(CTCPSocket *pSocket, HWND hWnd, BOOL bAsync)
{
//pSocket是SERVER的socket类,hWnd是主窗口句柄
int nLength = sizeof(SOCKADDR_IN);
SOCKADDR_IN sockClient;
int nResult;
if( pSocket == NULL ) return FALSE;
m_lpReceiveBuffer = (LPBYTE)GlobalAlloc( GPTR, MAX_PACKET_SIZE*4 );
if( !m_lpReceiveBuffer )
{
m_nErrorCode = SOCKET_ERROR_CREATE;
return FALSE;
}
m_lpSendBuffer = (LPBYTE)GlobalAlloc( GPTR, MAX_PACKET_SIZE+1 );
if( !m_lpSendBuffer )
{
m_nErrorCode = SOCKET_ERROR_CREATE;
return FALSE;
}
m_TCP_s = accept( pSocket->GetSocket(), (LPSOCKADDR)&sockClient, &nLength);
if( m_TCP_s == INVALID_SOCKET )
{
//套接字无效
m_nErrorCode = SOCKET_ERROR_ACCEPT;
return FALSE;
}
///获得对方的IP地址,保存到m_szHost
ipClient = sockClient.sin_addr;
m_szHost.Format( "%d.%d.%d.%d",
ipClient.S_un.S_un_b.s_b1,
ipClient.S_un.S_un_b.s_b2,
ipClient.S_un.S_un_b.s_b3,
ipClient.S_un.S_un_b.s_b4 );
if( bAsync == FALSE )
{
//不采用异步方式
//到这里就已经结束了
m_bSocketType = SOCKET_SERVER_TRANSFER;
m_bState = SOCKET_CONNECTED;
m_bCanWrite = TRUE;
return TRUE;
}
////////////异步接受
/////
////////////////////////////////////
m_hMainWnd = hWnd;
nResult = WSAAsyncSelect( m_TCP_s, hWnd, SOCKET_THREAD_TRANSFER, FD_READ|FD_WRITE|FD_CLOSE );
if( nResult == SOCKET_ERROR )
{
m_nErrorCode = SOCKET_ERROR_ACCEPT;
Close();
return FALSE;
}
////////成功了
/////////可以开始收发数据
///////////////////////////
m_bSocketType = SOCKET_SERVER_TRANSFER;
m_bState = SOCKET_CONNECTED;
m_bCanWrite = TRUE;
return TRUE;
}
CString CTCPSocket::GetHost()
{
return m_szHost;
}
BOOL CTCPSocket::Receive()
{
int nResult;
//把数据从网络中读到m_lpReceiveBuffer中
if( !m_lpReceiveBuffer ) return FALSE;
nResult = recv( m_TCP_s,
(char *)(m_lpReceiveBuffer+m_nEnd),
MAX_PACKET_SIZE,
0
);
ASSERT( nResult != 0 );
m_nEnd+=nResult;
//如何把内容传到对话框是关键问题
return (nResult!=0);
}
int CTCPSocket::Send(LPBYTE lpBuf, int nLen)
{
//把lpBuf中长度为nLen字节的数据发出
int nResult;
LPBYTE lpTemp;
int nSendLen;
if( m_bCanWrite == FALSE ) return SOCKET_ERROR_SEND;
if( nLen == 0 ) return SOCKET_ERROR_SEND;
if( nLen > MAX_PACKET_SIZE ) return SOCKET_ERROR_SEND;
if( lpBuf == NULL ) return SOCKET_ERROR_SEND;
memcpy( m_lpSendBuffer, lpBuf, nLen );
lpTemp = m_lpSendBuffer;
nSendLen = nLen;
//等待FD_WRITE
while( 1 )
{
nResult = send( m_TCP_s, (char *)lpTemp, nSendLen, 0 );
//可能网络发生错误
if( nResult == 0 ) return SOCKET_ERROR_CLOSE;
if( nResult == SOCKET_ERROR )
{
nResult = WSAGetLastError();
switch( nResult )
{
case WSAEWOULDBLOCK:
m_bCanWrite = FALSE;
return SOCKET_ERROR_BLOCK;
case WSAENETRESET:
return SOCKET_ERROR_RESET;
default:
return SOCKET_ERROR_SEND;
}
}
if( nResult < nSendLen )
{
lpTemp+=nResult;
nSendLen-=nResult;
}
else
{
return SOCKET_ERROR_NOERROR;
}
}
}
void CTCPSocket::EnableWrite()
{
m_bCanWrite = TRUE;
}
LPBYTE CTCPSocket::GetData(int *nLen)
{
LPBYTE lpTemp = NULL;
if( m_lpReceiveBuffer == NULL ) return NULL;
if( m_nBegin == m_nEnd ) return NULL;
if( m_nEnd-m_nBegin > MAX_PACKET_SIZE )
{
*nLen = MAX_PACKET_SIZE;
}
else *nLen = m_nEnd-m_nBegin;
lpTemp = m_lpReceiveBuffer+m_nBegin;
m_nBegin = 0;
m_nEnd = 0;
return lpTemp;
}
int CTCPSocket::SendFirstPacket()
{
//发送连接请求
char buf[300];
int nBytes;
if(
(confChat.bProxyUsable == PROXY_AUTH_UNSET)
||(confChat.bProxyUsable == PROXY_AUTH_NOPASS)
)
{
memset( buf, 0, 300 );
wsprintf( buf, "%s%s:%d%s",
"CONNECT ",
m_szHost,
m_nPort,
" HTTP/1.1\r\nUser-Agent: NetChat/0.1\r\n\r\n");
nBytes = strlen( buf );
return Send((LPBYTE)buf, nBytes );
}
else
{
memset( buf, 0, 300 );
wsprintf( buf, "%s%s:%d%s%s\r\n\r\n",
"CONNECT ",
m_szHost,
m_nPort,
" HTTP/1.1\r\nUser-Agent: PCTel/0.3\r\n",
(LPSTR)(LPCTSTR)confChat.szProxyPass
);
nBytes = strlen( buf );
return Send((LPBYTE)buf, nBytes);
}
}
BOOL CTCPSocket::ChangeHandle()
{
int nResult;
if( m_TCP_s == INVALID_SOCKET) return FALSE;
if( m_bSocketType != SOCKET_CLIENT ) return FALSE;
if( m_bState != SOCKET_CONNECTED ) return FALSE;
if( m_bUseProxy == FALSE ) return FALSE;
WSAAsyncSelect( m_TCP_s , m_hMainWnd, 0, 0 );
m_hMainWnd = m_hFinalWnd;
nResult = WSAAsyncSelect(
m_TCP_s,
m_hMainWnd,
SOCKET_THREAD_TRANSFER,
FD_READ|FD_WRITE|FD_CLOSE
);
if( nResult == SOCKET_ERROR )
{
m_nErrorCode = SOCKET_ERROR_CONNECT;
return FALSE;
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -