模型设计与实践---(二)IO模型ACCEPT

在上一篇中,先介绍了整个框架的类图。

下面拿WINDOW  的6个IO模型进行演练,对WIN 6种SOCKET IO模型不了解的建议大家网上搜一下,有好多老陈和女儿通信的幽默描述。我这里就不再说解,直接贴码。

socketSelectAccept.h

/********************************************************************
	创建时间:	2013/04/05

	文件名: 	socketSelectAccept.h
	描述:
			SOCKET I/O 模式 一 阻塞方式 (select),主要实现了阻塞
			方式的I/O工作模式。
	作者:		fengsh
	QQ  :		19985430
	电子邮件:	fengsh998@163.com
	Blog :      http://blog.csdn.net/fengsh998
	@CopyRight  fengsh

*********************************************************************/
#pragma once

#include "socketBase.h"
#include "string"

class CSocketSelect :
	public CSocketBase
{
private:
	void destroySocket();
	void stopthread();
	void disconnect();
public:
	CSocketSelect(void);
	~CSocketSelect(void);

	int startServer();
	int stopServer();
	bool sendtext(const std::string& content);

	void checkRecvicedMessage();

	SOCKET dataSocket;
	bool isexit;
private:
	void * acceptid;
	void * recvid;

};


socketSelectAccept.cpp

#include "socketSelectAccept.h"
#include "SocketConst.h"
#include "socketServerCallback.h"
#include "socketThread.h"

static void* appcet_thread(void* param);
static void* recv_thread(void* param);


CSocketSelect::CSocketSelect(void):isexit(false)
{
	dataSocket = NULL;
}

CSocketSelect::~CSocketSelect(void)
{
	//先将CALLBACK空置,防止线程回调到的界面已DELETE
	m_scallback = NULL;

	disconnect();
	destroySocket();
	isexit = true;
	stopthread();

	dataSocket = NULL;
}

void CSocketSelect::destroySocket()
{
	closesocket(m_listenSocket);
	WSACleanup();
	m_listenSocket =  NULL;
}

void CSocketSelect::stopthread()
{
	socket_thread_join(&acceptid);
	socket_thread_join(&recvid);
	acceptid = 0;
	recvid = 0;
}

int CSocketSelect::startServer()
{
	if (initSocket())
	{
		//创建检查ACCEPT线程
		socket_thread_create(&this->acceptid,appcet_thread,(void*)this);
		//创建不断查询消息线程
        isexit = false;
		checkRecvicedMessage();
		return 1;
	}
	return -1;
}

void CSocketSelect::disconnect()
{
	if (dataSocket)
	{
		closesocket(dataSocket);
		dataSocket = NULL;
	}
	
}

int CSocketSelect::stopServer()
{
	bool closeYes = true;
	if (m_scallback)
	{
		closeYes = dispatchcallback(cbServerClose,NULL);
	}
	if (closeYes)
	{
		isexit = true;
		disconnect();
		destroySocket();
		stopthread();

		dataSocket = NULL;
	}

	return 1;
}

bool CSocketSelect::sendtext( const std::string& content )
{
	return sendData(dataSocket,content);
}

void CSocketSelect::checkRecvicedMessage()
{
	socket_thread_create(&this->recvid,recv_thread,(void*)this);
}

//不停的进行查询是否有消息到来,耗U
//这里就是所谓的阻塞,不能去做其它事情了。
static void* recv_thread(void* param)
{
	if (!param)
	{
		return 0;
	}

	DISPATCHPARAM dp;
	
	char recvBuf[1024]={0};
	CSocketSelect *ss = (CSocketSelect*)param;

	while (1)
	{
		if (ss->isexit)
		{
			break;
		}
        memset(&dp,0,sizeof(DISPATCHPARAM));
		socket_thread_sleep(500);

		if (ss->dataSocket)
		{
			//每次都来查询有否消息。
			ss->dispatchcallback(cbReadyRev,NULL);
			int nRetSize=recv(ss->dataSocket,recvBuf,1024,0);

			if (nRetSize>0)
			{
				strcpy(dp.msg,recvBuf);
				//回调到界面
				ss->dispatchcallback(cbCommunication,&dp);
				//回调到接收完成
				ss->dispatchcallback(cbRecviced,NULL);
			}
			else if (nRetSize == 0)
				{//客户端主动断连了。0 
					ss->dataSocket = NULL;
					dp.errcode = WSAGetLastError();
					ss->dispatchcallback(cbDisconnect,&dp);
				}
			else if (nRetSize == -1)
			{
				//客户端异常断开10054 当客户端在监听recv动作时被关闭了socket就会引发
				//10053 服务器主动断开
				//10093 在没有任何客户端连接的情况下,服务器关闭数据SOCKET引发
				ss->dataSocket = NULL;
				strcpy(dp.errmsg,"client error.");
				dp.errcode = WSAGetLastError();
				ss->dispatchcallback(cbDisconnect,&dp);
			}
		}
	}

	return 0;
}


//阻塞等待客户端的连接。
static void* appcet_thread(void* param)
{
	CSocketSelect * ss = (CSocketSelect*)param;

	int nConNum=0;
	DISPATCHPARAM dp;
	memset(&dp,0,sizeof(DISPATCHPARAM));
	char hint[1024]={0};
	while(true)
	{

		SOCKADDR_IN addrClient;
		int addrClientSize=sizeof(SOCKADDR_IN);

		ss->dataSocket = accept(ss->m_listenSocket,(struct sockaddr*)&addrClient,&addrClientSize);
		if (ss->dataSocket==INVALID_SOCKET)
		{
			ss->dataSocket = NULL;
			if (ss->checkSocketError(WSAGetLastError()))
			{
				break;
			}
			
			continue;
		}
		else
		{
			nConNum++;
		
			strcpy(dp.info.ip,inet_ntoa(addrClient.sin_addr));
			dp.info.port = addrClient.sin_port;
			strcpy(dp.msg,hint);
			ss->dispatchcallback(cbHasConnect,&dp);
		}

	}
	return 0;
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

边缘998

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

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

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

打赏作者

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

抵扣说明:

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

余额充值