您的位置:首页 > 其它

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

2008-02-17 18:03 204 查看
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;

}

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

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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: