VC下CSocket非阻塞方式下的连接框架

作者:Wupei  |  发表时间:  |  所属分类:VC

CSocket非阻塞方式(不用自己建立线程)

1.服务端
应用非阻塞方式需要自己声明一个类继承CSokcet类

// MySocket.h : header file
class CMySocket : public CSocket
{
// Attributes
public:
	CServerDlg* m_pServerDlg;	//主窗口指针
// Operations
public:
	CMySocket();
	virtual ~CMySocket();

// Overrides
public:
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CMySocket)
	public:
	virtual void OnAccept(int nErrorCode);	//当准备连接时,系统调用
	virtual void OnReceive(int nErrorCode);	//当准备接受消息时,系统调用
	//}}AFX_VIRTUAL

	// Generated message map functions
	//{{AFX_MSG(CMySocket)
		// NOTE - the ClassWizard will add and remove member functions here.
	//}}AFX_MSG

// Implementation
protected:

};

// MySocket.cpp : implementation file

CMySocket::CMySocket(CServerDlg* pServerDlg)
{
	m_pServerDlg = pServerDlg;	//用于处理消息
}

CMySocket::~CMySocket()
{
}

// Do not edit the following lines, which are needed by ClassWizard.
#if 0
BEGIN_MESSAGE_MAP(CMySocket, CSocket)
	//{{AFX_MSG_MAP(CMySocket)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif	// 0

/////////////////////////////////////////////////////////////////////////////
// CMySocket member functions

void CMySocket::OnAccept(int nErrorCode) 
{
	// TODO: Add your specialized code here and/or call the base class
	//处理连接请求
	m_pServerDlg->ServerAccept();
	
	CSocket::OnAccept(nErrorCode);
}

void CMySocket::OnReceive(int nErrorCode) 
{
	// TODO: Add your specialized code here and/or call the base class
	//处理接受消息请求
	m_pServerDlg->ServerReceive(this);	//传入本身Socket

	CSocket::OnReceive(nErrorCode);
}

////////////////////////////////////////////////////
// ServerDlg.h : header file

CMySocket* m_pServer;	//添加Socket指针
CPtrArray m_ConnectArray;	//用于保存连接指针的容器

////////////////////////////////////////////////////
// ServerDlg.cpp : implementation file

void CServerDlg::ServerInit()	//服务端初始化,供别的函数调用
{
	m_pServer = new CMySocket(this);	//传入窗口指针
	if(!m_pServer->Create(61111))	//指明端口
	{
		MessageBox("服务器初始化错误n程序退出");
		delete m_pServer;
		return;
	}
	if(!m_pServer->Listen())	//开始监听
	{
		MessageBox("服务器初始化错误n程序退出");
		delete m_pServer;
		return;
	}
}
void CServerDlg::ServerAccept()	//有客户端连接,系统调用
{
	CMySocket* connect = new CMySocket(this);	//建立连接用Socket

	if(!m_pServer->Accept(*connect))
	{
		MessageBox("客户端连接错误!");
		delete connect;
	}
	
	m_ConnectArray.Add(connect);	//把这个连接添加进容器
}
void CServerDlg::ServerReceive(CMySocket* connect)	//连接发来数据,准备接收
{
	char msg[100];
	connect->Receive(msg,100);	//接受数据
	MessageBox(CString(msg));
}
void CServerDlg::SocketSend(CMySocket* connect, CString msg)	//Socket发送数据
{
	char* str= msg.GetBuffer(msg.GetLength());
	connect->Send(str,msg.GetLength());	//发送数据
}
void CServerDlg::ServerSendToAllConnect(char* pChar)	//发送给所有客户端数据的函数
{
	for(int i=0; i<=m_ConnectArray.GetSize()-1; i++)	//遍历连接容器
	{
		((CMySocket*)m_ConnectArray[i])->Send(pChar,100);	//发送
	}
}
void CServerDlg::ServerClose()
{
	//发送踢出消息,使客户端自动断开连接
	//ServerSendToAllConnect("01");	//用户实现方式不同
	
	//清理服务器连接
	m_pServer->Close();
	delete m_pServer;

	//清理客户端连接
	for(int i=0; i<=m_ConnectArray.GetSize()-1; i++)
	{
		((CMySocket*)m_ConnectArray[i])->Close();
		delete (CMySocket*)m_ConnectArray[i];
	}
	m_ConnectArray.RemoveAll();
}

注意:客户端连接与断开时,必须根据实际情况,更新存放连接容器,否则会出现错误

2.客户端

//也使用了CMySocket,代码同服务端CMySokcet一样,只不过不用响应OnAccept事件

//////////////////////////////////////////////////
// ClientDlg.h : header file
CMySocket* m_pClient;	//本身连接用Socket

//////////////////////////////////////////////////
// ClientDlg.cpp : implementation file

bool CClientDlg::ClientInit()
{
	m_pClient = new CMySocket(this);
	if(!m_pClient->Create())
	{
		delete m_pClient;
		MessageBox("客户端初始化错误!n");
		return 0;
	}

	if(!WSAEINVAL==m_pClient->Connect("127.0.0.1",61111))	//连接服务器IP的某端口(端口须和上面一直)
	{
		delete m_pClient;
		MessageBox("客户端初始化错误!n");
		return 0;
	}

	return 1;
}
void CClientDlg::ClientReceive(CMySocket* Socket)	//客户端接受数据
{
	char ReceiveChar[100];
	Socket->Receive(ReceiveChar,100);
	CString ReceiveMsg(ReceiveChar);
	MessageBox(ReceiveMsg);
}
void CClientDlg::ClientSend(CString msg)	//客户端发送数据
{
	char* str= msg.GetBuffer(msg.GetLength());
	m_pClient->Send(str,msg.GetLength());	//发送数据
}
bool CClientDlg::ClientClose()		//客户端断开连接
{
	//应发送数据,告诉服务端,自己断开连接,更新服务端容器内的连接
	//m_Client->Send("02",100);//用户实现方式不同
	
	if(m_pClient)
	{
		m_pClient->Close();
		delete m_pClient;
		return 1;
	}
	return 0;
}

注意:客户端连接与断开时,必须根据实际情况,让服务端只是,自己连接与断开了,及时更新服务端的存放连接的容器

下面是我做的一个超级简单的聊天室的流程图,仅供参考
超级简易聊天室流程图

Trackback from your site.

请在这里留言: