模型设计与实践---(四)异步选择IO(AnsySelect IO)

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);
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

边缘998

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值