📄 clientsocket.cpp
字号:
// ClientSocket.cpp : implementation file
#include "stdafx.h"
#include "Client.h"
#include "ClientDlg.h"
#include "ClientSocket.h"
#include "..\\Common.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CClientSocket
CClientSocket::CClientSocket(CClientDlg* pDlg)
{
m_pMainWnd = pDlg;
}
CClientSocket::~CClientSocket()
{
}
// Do not edit the following lines, which are needed by ClassWizard.
#if 0
BEGIN_MESSAGE_MAP(CClientSocket, CAsyncSocket)
//{{AFX_MSG_MAP(CClientSocket)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif // 0
/////////////////////////////////////////////////////////////////////////////
// CClientSocket member functions
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void CClientSocket::OnConnect(int nErrorCode)
{
CString strMsg;
if (nErrorCode != 0) {
strMsg.Format(IDS_DISCONNECTED,
m_pMainWnd->GetHostAddr(),
m_pMainWnd->GetHostPort());
m_pMainWnd->AddMessage(strMsg);
return;
}
CString strIP;
UINT uPort;
if (!GetPeerName(strIP, uPort)) {
TRACE0("fail to get peer information.\n");
return;
}
//
m_pMainWnd->SetConnected(TRUE);
m_pMainWnd->CreateChatSocket();
if (SendLoginInfo() <= 0) {
TRACE0("fail to send log in information to server.\n");
return;
}
// 更新显示
strMsg.Format(IDS_SERVINFO, strIP, uPort, "已");
m_pMainWnd->SetDlgItemText(IDC_SERVINFO_STATIC, strMsg);
strMsg.Format(IDS_CONNECTED, strIP, uPort);
m_pMainWnd->AddMessage(strMsg);
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void CClientSocket::OnClose(int nErrorCode)
{
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void CClientSocket::OnReceive(int nErrorCode)
{
if (nErrorCode != 0) {
return;
}
// 注销FD_READ事件
if (!AsyncSelect(0)) {
TRACE0("AsyncSelect error.\n");
return;
}
// 读数据包类型
WORD wPackType = 0;
if (Receive(&wPackType, sizeof(wPackType), 0) != sizeof(wPackType))
{
TRACE0("Unable to receive package type!");
}
// 分析数据包类型
switch (wPackType)
{
case PACKAGE_USERLIST:
OnReceiveUserList();
break;
case PACKAGE_USERADD:
OnReceiveUserAdd();
break;
case PACKAGE_USERDEL:
OnReceiveUserDel();
break;
case PACKAGE_MESSAGE: // 来自服务器的消息
OnReceiveMessage();
break;
case PACKAGE_LOGOUT:
case PACKAGE_SERVERCLOSE:
OnOffline(wPackType);
return; //注意, 既然已关闭套接字, 故直接返回
default:
break;
}
// 重新注册网络事件
if (!AsyncSelect(FD_READ | FD_CLOSE | FD_CONNECT)) {
TRACE0("AsyncSelect error.\n");
return;
}
}
void CClientSocket::OnReceiveUserList()
{
int len = 0;
// 读取列表长度
if (Receive((void*)&len, sizeof(len), 0) != sizeof(len))
{
TRACE0("Unable to receive name list length.");
return;
}
//
if (len == 0) {
return;
}
//
USER_INFO* pArray = new USER_INFO[len];
ASSERT(pArray != NULL);
// receive user list
if (Receive((void*)pArray, sizeof(USER_INFO) * len, 0) !=
(int)sizeof(USER_INFO) * len) {
TRACE0("Unable to receive name list data.");
return;
}
// 将其添加到用户列表
USER_INFO* pInfo = pArray;
for (int i = 0; i < len; i++, pInfo++) {
USER_INFO* p = new USER_INFO;
memcpy((void*)p, (void*)pInfo, sizeof(USER_INFO));
m_pMainWnd->AddUserInfo(p);
}
// 更新组合框的显示
m_pMainWnd->AddNameList();
//
delete pArray;
}
void CClientSocket::OnReceiveUserAdd()
{
USER_INFO* pInfo = new USER_INFO;
ASSERT(pInfo != NULL);
if (Receive((void*)pInfo, sizeof(USER_INFO), 0)
!= sizeof(USER_INFO)) {
TRACE0("Unable to receive newly log in user data.\n");
return;
}
// 将其添加到用户列表
m_pMainWnd->AddUserInfo(pInfo);
// 更新组合框显示
m_pMainWnd->AddNameList();
// 向消息框加入新消息
CString strMsg;
strMsg.Format(IDS_USERJOIN, pInfo->name,
inet_ntoa(*(in_addr*)&pInfo->addr),
pInfo->port);
m_pMainWnd->AddMessage(strMsg);
}
void CClientSocket::OnReceiveUserDel()
{
USER_INFO* pInfo = new USER_INFO;
ASSERT(pInfo != NULL);
if (Receive((void*)pInfo, sizeof(USER_INFO), 0)
!= sizeof(USER_INFO)) {
TRACE0("Unable to receive log out user data.\n");
return;
}
// remove user infomatioin from list
if (!m_pMainWnd->DelUserInfo(pInfo)) {
TRACE1("No such user %s.\n", pInfo->name);
return;
}
// 更新组合框显示
m_pMainWnd->AddNameList();
// 向消息框增加消息
CString strMsg;
strMsg.Format(IDS_USERLEAVE, pInfo->name,
inet_ntoa(*(in_addr*)&pInfo->addr),
ntohs(pInfo->port));
m_pMainWnd->AddMessage(strMsg);
// 删除之
delete pInfo;
}
void CClientSocket::OnReceiveMessage()
{
char* pBuf = new char[0x1000]; // 4K byte
ASSERT(pBuf != NULL);
if (Receive((void*)pBuf, 0x1000, 0) <= 0)
{
TRACE0("fail to receive message from sever.\n");
return;
}
// 得到对等方信息
CString strDestAddr;
UINT uDestPort;
if (!GetPeerName(strDestAddr, uDestPort)) {
TRACE0("fail to get peer information.\n");
return;
}
// 格式化消息文本
CString strMsg;
strMsg.Format(IDS_MESSAGE, strDestAddr, uDestPort, pBuf);
m_pMainWnd->AddMessage(strMsg);
delete [] pBuf;
}
void CClientSocket::OnOffline(WORD wType)
{
// 格式化主机信息的Static
CString strMsg;
strMsg.Format(IDS_SERVINFO, "0.0.0.0", 0, "未");
m_pMainWnd->SetDlgItemText(IDC_SERVINFO_STATIC, strMsg);
// 添加离线原因的消息
if (wType == PACKAGE_LOGOUT) {
strMsg.LoadString(IDS_LOGOUT);
} else if (wType == PACKAGE_SERVERCLOSE) {
strMsg.Format(IDS_SERVERCLOSE,
m_pMainWnd->GetHostAddr(),
m_pMainWnd->GetHostPort());
}
m_pMainWnd->AddMessage(strMsg);
// 关闭并设定状态变量的状态
m_pMainWnd->ResetUserInfo();
m_pMainWnd->SetClientSocket(NULL);
m_pMainWnd->SetConnected(FALSE);
Close();
delete this;
}
int CClientSocket::SendLoginInfo()
{
const int LEN = sizeof(WORD) + sizeof(LOGIN_INFO);
char pBuf[LEN];
ASSERT(pBuf != NULL);
// 填充pBuf
*(WORD*)pBuf = PACKAGE_LOGIN;
LOGIN_INFO* pLogin = (LOGIN_INFO*)(pBuf + sizeof(WORD));
strcpy(pLogin->name, m_pMainWnd->GetUserName());
strcpy(pLogin->password, m_pMainWnd->GetUserPassword());
// 发送之
return Send((void*)pBuf, LEN, 0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -