CSocket非阻塞方式(不用自己建立线程)
1. 服务端
应用非阻塞方式需要自己声明一个类继承CSokcet类
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:
-
-
};
href="http://www.j2megame.org/wupei/plugins/plogeshi/styles/plogeshi.css" type="text/css" rel="stylesheet" />
-
// 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;
-
}
注意:客户端连接与断开时,必须根据实际情况,让服务端只是,自己连接与断开了,及时更新服务端的存放连接的容器
下面是我做的一个超级简单的聊天室的流程图,仅供参考