网狐框架分析九--TCPSocket.cpp

---
#1.流程
首先建立socket:
m_hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);


***绑定窗口:***
iErrorCode = WSAAsyncSelect(m_hSocket, m_hWnd, WM_SOCKET_NOTIFY, FD_READ | FD_CONNECT | FD_CLOSE);//WM_SOCKET_NOTIFY用来接受网络返回消息


ON_MESSAGE(WM_SOCKET_NOTIFY, OnSocketNotify)//通过这个接受网络消息并跳转函数


***//SOCKET 消息处理程序***
LRESULT CTCPSocket::OnSocketNotify(WPARAM wParam, LPARAM lParam)
{
switch (WSAGETSELECTEVENT(lParam))
{
case FD_CONNECT: //网络连接
{
return OnSocketNotifyConnect(wParam, lParam);
}
case FD_READ:  //数据读取
{
return OnSocketNotifyRead(wParam, lParam);
}
case FD_CLOSE: //网络关闭
{
return OnSocketNotifyClose(wParam, lParam);
}
}
return 0;
}


***//处理网络连接事件***
LRESULT CTCPSocket::OnSocketNotifyConnect(WPARAM wParam, LPARAM lParam)
{
//判断状态
int iErrorCode = WSAGETSELECTERROR(lParam);
if (iErrorCode == 0) m_cbSocketStatus = SOCKET_STATUS_CONNECT;
else CloseSocket(SHUT_REASON_TIME_OUT);
//发送通知
m_pITCPSocketSink->OnEventTCPSocketLink(GetSocketID(), GetLastError());
return 1;
}


//对m_pITCPSocketSink解释


//在外部定义网络接口
interface ITCPSocketSink : public IUnknownEx
{
public:
//连接事件
virtual bool __cdecl OnEventTCPSocketLink(WORD wSocketID, INT nErrorCode)=NULL;
//关闭事件
virtual bool __cdecl OnEventTCPSocketShut(WORD wSocketID, BYTE cbShutReason)=NULL;
//读取事件
virtual bool __cdecl OnEventTCPSocketRead(WORD wSocketID, CMD_Command Command, VOID * pData, WORD wDataSize)=NULL;
};


然后在内部定义成员变量:
ITCPSocketSink * m_pITCPSocketSink; //回调接口


接着其它类引用此接口文件
//游戏广场
class CPlazaViewItem :public ITCPSocketSink
{
    CTCPSocketHelper m_ClientSocket; //网络连接
    //连接事件
virtual bool __cdecl OnEventTCPSocketLink(WORD wSocketID, INT nErrorCode);//子类中实现接口,并做一些相应的处理, 比如发送消息等
}


CTCPsocketHelper定义转到:
DECLARE_MODULE_HELPER(TCPSocket,NETWORK_SERVICE_DLL_NAME,"CreateTCPSocket")


DECLARE_MODULE_HELPER定义转到:
//组件辅助类宏
#define DECLARE_MODULE_HELPER(OBJECT_NAME,MODULE_DLL_NAME,CREATE_FUNCTION_NAME) \
class C##OBJECT_NAME##Helper : public CTempldateHelper<I##OBJECT_NAME> \
{ \
public: \
C##OBJECT_NAME##Helper() : CTempldateHelper<I##OBJECT_NAME>(IID_I##OBJECT_NAME, \
VER_I##OBJECT_NAME,MODULE_DLL_NAME,CREATE_FUNCTION_NAME) { } \
};




//cpp中对接口进行具体实现
bool __cdecl CPlazaViewItem::OnEventTCPSocketLink(WORD wSocketID, INT nErrorCode)
{
    m_DlgLogon.SendLogonPacket(m_ClientSocket.GetInterface());//此处发包
}
CDlgLogon m_DlgLogon; //登录对话框


//跳转到发包对话框类,发包
bool CDlgLogon::SendLogonPacket(ITCPSocket * pIClientSocke)
{
    pIClientSocke->SendData(MDM_GP_LOGON,SUB_GP_LOGON_ACCOUNTS,cbBuffer,sizeof(CMD_GP_LogonByAccounts)+Packet.GetDataSize());
}


//跳转到TCPSocket.cpp函数的SendData()函数,经过SendDataBuffer()转换,调用底层的send函数发送信息
send(m_hSocket, (char *)pBuffer + wSended, wSendSize - wSended, 0);


---
***//处理网络读取消息***
LRESULT CTCPSocket::OnSocketNotifyRead(WPARAM wParam, LPARAM lParam)
{
    recv(m_hSocket, (char *)m_cbRecvBuf + m_wRecvSize, sizeof(m_cbRecvBuf) - m_wRecvSize, 0);//recv接收函数
     m_pITCPSocketSink->OnEventTCPSocketRead(GetSocketID(), Command, pDataBuffer, wDataSize);//处理函数,此接口函数调用到子类处理
}
//例如游戏广场 //网络读取消息
bool __cdecl CPlazaViewItem::OnEventTCPSocketRead(WORD wSocketID, CMD_Command Command, VOID * pData, WORD wDataSize)
{
switch (Command.wMainCmdID)
{
case MDM_GP_LOGON: //登录消息
{
return OnSocketMainLogon(Command,pData,wDataSize);
}
case MDM_GP_SERVER_LIST: //列表消息
{
return OnSocketMainServerList(Command,pData,wDataSize);
}
case MDM_GP_SYSTEM: //系统消息
{
return OnSocketMainSystem(Command,pData,wDataSize);
}
case MDM_GP_USER: //用户消息
{
return OnSocketMainUser(Command,pData,wDataSize);
}
}
return true;
}




---


至此发现,在网络模型CTCPSocket中,用到了关键:接口模型,通过接口这一模型帮助,避免了直接调用子类,最大限度解耦了关系。当子类需要用到此网络模型时,只需要引用此接口,然后实现它,并在成员变量中声明它便可方便灵活使用了。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值