socketAsynSelect.h
/********************************************************************
创建时间: 2013/04/11
文件名: socketAsynSelect.h
描述:
异步选择I/O模型
需要有界面,要向UI抛WIN 消息。需要窗口句柄
作者: fengsh
QQ : 19985430
电子邮件: fengsh998@163.com
Blog : http://blog.csdn.net/fengsh998
@CopyRight fengsh
*********************************************************************/
#pragma once
#include "socketbase.h"
//引入这个才能在DLL中使用SendMessage的API
#pragma comment(lib, "User32.lib")
class CSocketAsynSelect :
public CSocketBase
{
private:
void cancelEventNotify();
protected:
void processAsynSelect();
public:
CSocketAsynSelect(void);
~CSocketAsynSelect(void);
int startServer() ;
int stopServer() ;
bool sendtext(const std::string& content) ;
void asynResponse(unsigned int wParam, long lParam);
private:
SOCKET datasocket;
};
socketAsynSelect.cpp
#include "socketAsynSelect.h"
#include "SocketConst.h"
CSocketAsynSelect::CSocketAsynSelect(void)
{
}
CSocketAsynSelect::~CSocketAsynSelect(void)
{
}
int CSocketAsynSelect::startServer()
{
if (initSocket())
{
processAsynSelect();
return 1;
}
return -1;
}
int CSocketAsynSelect::stopServer()
{
dispatchcallback(cbServerClose,NULL);
closesocket(datasocket);
closesocket(m_listenSocket);
dispatchcallback(cbDisconnect,NULL);
return -1;
}
bool CSocketAsynSelect::sendtext( const std::string& content )
{
return sendData(datasocket,content);
}
void CSocketAsynSelect::processAsynSelect()
{
if (m_handle)
{
if(SOCKET_ERROR == WSAAsyncSelect(m_listenSocket,(HWND)this->m_handle,WM_ASYNSOCKET,FD_ACCEPT))
{
DISPATCHPARAM dp;
memset(&dp,0,sizeof(DISPATCHPARAM));
dp.errcode = WSAGetLastError();
dispatchcallback(cbError,&dp);
}
//SendMessage((HWND)this->m_handle,WM_ASYNSOCKET,1,1);
}
else
{
//dispatchcallback(cbError,)
}
}
/*
值 说明 触发条件
FD_READ 套接口有可读消息通知 recv,recvfrom,WSARecv或WSARecvFrom
FD_WRITE 套接口有可发消息通知 send,sendto,WSASend或WSASendTo
FD_OOB 套件口有外带数据消息通知 recv,recvfrom,WSARecv或WSARecvFrom
FD_ACCEPT 套接口有链接请求消息通知 accept或WSAAccept(错误码不能WSATRY_AGAIN)
FD_CONNECT 希望得到connect或多点join操作完成信息通知 无
FD_CLOSE (面向连接) 套接口关闭消息通知 无
FD_QOS 套接口QOS状态发生变化消息通知 WSAIoctl(SIO_GET_QOS)
FD_GROUP_QOS 保留 Reserved
FD_ROUTING_INTERFACE_CHANGE 特定方向的路由接口发生改变消息通知。 WSAIoctl(SIO_ROUTING_INTERFACE_CHANGE)
FD_ADDRESS_LIST_CHANGE 得到本地地址列表上套接口协议族发生改变通知。 WSAIoctl(SIO_ADDRESS_LIST_CHANGE)
*/
void CSocketAsynSelect::asynResponse( unsigned int wParam, long lParam )
{
if (WSAGETSELECTERROR(lParam))
{
closesocket(wParam);
return ;
}
DISPATCHPARAM dp;
memset(&dp,0,sizeof(DISPATCHPARAM));
switch(lParam)
{
case FD_ACCEPT:
{
SOCKADDR_IN addrClient;
int naddrClientSize=sizeof(SOCKADDR_IN);
datasocket=accept(wParam,(struct sockaddr *)&addrClient,&naddrClientSize);
if (datasocket==INVALID_SOCKET)
{
datasocket = NULL;
checkSocketError(WSAGetLastError());
}
else
{
strcpy(dp.info.ip,inet_ntoa(addrClient.sin_addr));
dp.info.port = addrClient.sin_port;
dispatchcallback(cbHasConnect,&dp);
}
WSAAsyncSelect(datasocket,(HWND)m_handle,WM_ASYNSOCKET,FD_READ | FD_WRITE | FD_CLOSE);
}
break;
case FD_READ:
{
int nRetSize = 0;
char bufMsg[BUFFERMAX];
dispatchcallback(cbReadyRev,NULL);
nRetSize=recv(wParam,bufMsg,BUFFERMAX,0);
if (nRetSize>0)
{
strcpy(dp.msg,bufMsg);
//回调到界面
dispatchcallback(cbCommunication,&dp);
//回调到接收完成
dispatchcallback(cbRecviced,NULL);
}
else if (nRetSize == 0)
{//客户端主动断连了。0
datasocket = NULL;
dp.errcode = WSAGetLastError();
dispatchcallback(cbDisconnect,&dp);
}
else if (nRetSize == -1)
{
//客户端异常断开10054 当客户端在监听recv动作时被关闭了socket就会引发
//10053 服务器主动断开
//10093 在没有任何客户端连接的情况下,服务器关闭数据SOCKET引发
datasocket = NULL;
strcpy(dp.errmsg,"client error.");
dp.errcode = WSAGetLastError();
dispatchcallback(cbDisconnect,&dp);
}
}
break;
case FD_WRITE:
{
}
break;
case FD_CLOSE:
{
closesocket(wParam);
dispatchcallback(cbDisconnect,NULL);
}
break;
default:
break;
}
}
void CSocketAsynSelect::cancelEventNotify()
{
WSAAsyncSelect(m_listenSocket,(HWND)this->m_handle, 0, 0);
}