MFC-TCP网络编程服务端-Socket

目录

1、通过Socket建立服务端:

2、UI设计:

3、代码的实现:

(1)、CListenSocket类

(2)、CConnectSocket类

(3)、CTcpServerDlg类


1、通过Socket建立服务端:

(1)、创建一个Socket对象并绑定一个端口:CListenSocket 监听Socket

(2)、通过Listen()函数,监听来自客户端的连接请求

(3)、连接请求到来之后,建立一个通信用的Socket,CConnectSocket,并且加入数组中

(4)、使用Send()、Receive()函数,接收客户端发送的数据,并遍历数组,一次转发消息

2、UI设计:

3、代码的实现:

(1)、CListenSocket类

CListenSocket的目的是等待客户端的连接请求,继承Socket类,重写Socket的OnAccept函数,创建Socket对象,连接的初始化和等待客户端连接。

CListenSocket.h中

CListenSocket(CTcpServerDlg * pdlg);//传递对话框的指针

~CListenSocket();

virtual void OnAccept(int nErrorCode);//重写父类

CTcpServerDlg *m_pMainDlg;//接收传递的对话框指针

CListenSocket.cpp中

CListenSocket::CListenSocket(CTcpServerDlg * pdlg)

{

m_pMainDlg = pdlg; //初始化接收的对话框指针

}

void CListenSocket::OnAccept(int nErrorCode)

{

// TODO: 在此添加专用代码和/或调用基类

CSocket::OnAccept(nErrorCode);

m_pMainDlg->ProcessPendingAccept();//对于连接函数的处理放在对话框函数中处理

}

(2)、CConnectSocket类

CConnectSocket的目的是通讯用的Socket,继承Socket类,重写Socket的OnReceive函数,数据的接收和处理以及数据的解析。

CConnectSocket.h中

CConnectSocket(CTcpServerDlg *pdlg);

~CConnectSocket();

virtual void OnReceive(int nErrorCode);

CTcpServerDlg *m_pMainDlg;

CConnectSocket.cpp中

CConnectSocket::CConnectSocket(CTcpServerDlg *pdlg)

{

m_pMainDlg = pdlg;

}

void CConnectSocket::OnReceive(int nErrorCode)

{

// TODO: 在此添加专用代码和/或调用基类

CSocket::OnReceive(nErrorCode);

m_pMainDlg->ProcessPendingRead(this);//接收消息必须要传递指针进去,调用接收函数

}

(3)、CTcpServerDlg类

1)、声明服务端用于监听的socket

//服务端声明的用于监听的socket

CListenSocket *m_pListenSocket;

2)、声明一个CArray的对象,里面存放的CConectSocket指针

CArray<CConnectSocket*, CConnectSocket*&>m_ConnectSocketList;

//m_ConnectSocketList是CArray的一个对象,里面放着CConnectSocket的指针,并且可以对里面的数据进行访问和修改。

// CConnectSocket*&当数组元素被传递给函数时,使用引用方式传递元素,可以有效避免不必要的拷贝和内存开销。

3)、定义一个结构体,保存客户端的IP和Port

struct ClientAddr

{

CString strIp;

UINT uiPort;

};

4)、框架类的入口函数初始化监听Socket和端口号

m_pListenSocket = new CListenSocket(this);

//m_pListenSocket用来监听服务器的连接所以要分配内存

m_pListenSocket->Create(8080);

//初始化端口号

if (!m_pListenSocket->Listen())

{

MessageBox(L"监听失败!");

return FALSE;

}

5)、实现ProcessPendingAccept()函数

主要实现监听服务器的连接,监听到了就加到列表中

CConnectSocket *pConnectSocket = new CConnectSocket(this);

if (m_pListenSocket->Accept(*pConnectSocket))

{

m_ConnectSocketList.Add(pConnectSocket);

}

else {

delete pConnectSocket;

}

6)、实现ProcessPendingRead()函数

数据的接收,并且存放在buff中

TCHAR buff[4096];//存放接收到的数据

//接收数据

int nRead = connectSocket->Receive(buff, 4096);

if (nRead == SOCKET_ERROR)

{

return;

}

buff[nRead] = L'\0';//接收到的数据末尾加上结束符

CString strTemp(buff);//格式化buff

把连接到的客户端IP和Port存放在结构体中

ClientAddr clientAddr;//用来存放客户端的IP和Port

//获取连接上来的客户端的IP和端口

connectSocket->GetPeerName(clientAddr.strIp, clientAddr.uiPort);

解析数据:加入房间enter

int i = 0;

//解析数据

if (strTemp.CompareNoCase(L"enter") == 0)

{

//通知其他客户端有人进入房间

CString strEnterMsg;

strEnterMsg.Format(L"系统消息:%s(%d)进入了房间", clientAddr.strIp, clientAddr.uiPort);

for ( i;i<m_ConnectSocketList.GetSize();i++)

{//遍历每一个客户端,并且发送消息给每个客户端。

CConnectSocket *& tempClient = m_ConnectSocketList.ElementAt(i);

tempClient->Send(strEnterMsg, strEnterMsg.GetLength() + 100);

}

显示到界面

//更新界面

SetDlgItemInt(IDC_EDIT_NUMBER, m_ConnectSocketList.GetSize());//显示当前客户端人数

CString ALmSG;

GetDlgItemText(IDC_EDIT_MESSAGE, ALmSG);//EDIT上显示的之前的消息

SetDlgItemText(IDC_EDIT_MESSAGE, ALmSG + L"\r\n" + strEnterMsg);

//显示的现在的消息加上之前的消息

解析数据:离开房间leave

//从列表中移除

for (i;i<m_ConnectSocketList.GetSize();i++)

{

CConnectSocket *&temClient = m_ConnectSocketList.ElementAt(i);

ClientAddr temClientAddr;

temClient->GetPeerName(temClientAddr.strIp, temClientAddr.uiPort);

if (temClientAddr.uiPort == clientAddr.uiPort && temClientAddr.strIp.Compare(clientAddr.strIp) == 0)

{//当前移除的IP和Port如果和加入的时候存放在结构体的一样直接跳出循环删除

break;

}

if (i<m_ConnectSocketList.GetSize())

{

m_ConnectSocketList.RemoveAt(i);

}

发送给每一个客户端消息

//通知所有人

CString strleaveMsg;

strleaveMsg.Format(L"系统消息:%s(%d)进入了房间", clientAddr.strIp, clientAddr.uiPort);

for (i; i < m_ConnectSocketList.GetSize(); i++)

{

CConnectSocket *& tempClient = m_ConnectSocketList.ElementAt(i);

tempClient->Send(strleaveMsg, strleaveMsg.GetLength() + 100);

}

更新界面

//更新界面

SetDlgItemInt(IDC_EDIT_NUMBER, m_ConnectSocketList.GetSize());

CString ALmSG;

GetDlgItemText(IDC_EDIT_MESSAGE, ALmSG);

SetDlgItemText(IDC_EDIT_MESSAGE, ALmSG + L"\r\n" + strleaveMsg);

发送的是普通消息

//遍历每一个客户端发出,然后更新界面即可

CString strMsg;

strMsg.Format(L"%s(%d):%s", clientAddr.strIp, clientAddr.uiPort,strTemp);

for (i; i < m_ConnectSocketList.GetSize(); i++)

{

CConnectSocket *& tempClient = m_ConnectSocketList.ElementAt(i);

tempClient->Send(strMsg, strMsg.GetLength() + 100);

}

//更新界面

SetDlgItemInt(IDC_EDIT_NUMBER, m_ConnectSocketList.GetSize());

CString ALmSG;

GetDlgItemText(IDC_EDIT_MESSAGE, ALmSG);

SetDlgItemText(IDC_EDIT_MESSAGE, ALmSG + L"\r\n" + strMsg);

相关推荐
Spring_java_gg5 分钟前
如何抵御 Linux 服务器黑客威胁和攻击
linux·服务器·网络·安全·web安全
此生只爱蛋5 分钟前
【手撕排序2】快速排序
c语言·c++·算法·排序算法
何曾参静谧25 分钟前
「C/C++」C/C++ 指针篇 之 指针运算
c语言·开发语言·c++
lulu_gh_yu1 小时前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法
方方怪1 小时前
与IP网络规划相关的知识点
服务器·网络·tcp/ip
ULTRA??2 小时前
C加加中的结构化绑定(解包,折叠展开)
开发语言·c++
weixin_442643422 小时前
推荐FileLink数据跨网摆渡系统 — 安全、高效的数据传输解决方案
服务器·网络·安全·filelink数据摆渡系统
凌云行者2 小时前
OpenGL入门005——使用Shader类管理着色器
c++·cmake·opengl
凌云行者2 小时前
OpenGL入门006——着色器在纹理混合中的应用
c++·cmake·opengl
阑梦清川2 小时前
JavaEE初阶---网络原理(五)---HTTP协议
网络·http·java-ee