VC下CSocket非阻塞方式下的连接框架
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.