MFC-TCP网络编程客户端-Socket

目录

1、客户端创建流程:

2、UI设计:

3、代码实现:

(1)、ConnectSocket中重写OnReceive函数接收信息

(2)、框架类入口函数初始化

(3)、加入房间功能实现

(4)、离开房间功能实现

(5)、发送消息功能实现

(6)、OnPendingRead函数实现

4、最终运行结果:


1、客户端创建流程:

(1)、创建一个Socket对象并且自动绑定一个端口。

(2)、调用Connect()函数,建立一个到服务端的连接。

(3)、发送一个特殊消息进入房间enter。

(4)、使用Receive()函数,Send函数收发数据。

(5)、发送一个特殊消息退出房间leave。

2、UI设计:

3、代码实现:

(1)、ConnectSocket中重写OnReceive函数接收信息

CConnectSocket(CTcpClientDlg *pdlg);//框架类的指针,目的处理函数得放在框架中

~CConnectSocket();

CTcpClientDlg * m_pMainDlg;

virtual void OnReceive(int nErrorCode);
void CConnectSocket::OnReceive(int nErrorCode)

{

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

CSocket::OnReceive(nErrorCode);

m_pMainDlg->OnPendingRead();//处理函数在框架中,因为显示在对话框中

}

(2)、框架类入口函数初始化

//初始化服务端的IP,Port放在显示在UI

SetDlgItemText(IDC_EDIT_SERVER_IP, L"127.0.0.1");

SetDlgItemText(IDC_EDIT_SERVER_PORT, L"8080");

//设置各个按钮控件的状态

GetDlgItem(IDC_BUTTON_ENTER_ROOM)->EnableWindow(TRUE);

GetDlgItem(IDC_BUTTON_LEAVE_ROOM)->EnableWindow(FALSE);

GetDlgItem(IDC_BUTTON_SEND)->EnableWindow(FALSE);

//设置EDIT控件的只读或者可写

((CEdit*)GetDlgItem(IDC_EDIT_SEND_MESSAGE))->SetReadOnly(TRUE);

((CEdit*)GetDlgItem(IDC_EDIT_SERVER_PORT))->SetReadOnly(TRUE);

((CEdit*)GetDlgItem(IDC_EDIT_SERVER_IP))->SetReadOnly(TRUE);

(3)、加入房间功能实现

随机分配一个空闲的端口号

// 创建tcp套接字并且绑定一个自动分配的端口号

m_Pconnect = new CConnectSocket(this);

m_Pconnect->Create();

把本地的IP和Port显示在UI

//获取本地的端口和IP,并显示在UI

CString strlocalIP;

UINT uilocalPort;

m_Pconnect->GetSockName(strlocalIP, uilocalPort);

SetDlgItemText(IDC_EDIT_LOCAL_IP, strlocalIP);

SetDlgItemInt(IDC_EDIT_LOCAL_PORT, uilocalPort);

补充:建立TCP通讯的条件:

服务端和客户端的俩个端口得是空闲端口,客户端指定发送信息的IP地址,客户端在指定的IP上等待连接,同时还得有TCP\IP协议。

调用Connect连接服务端和客户端

//调用connect函数连接服务端

CString strServerIP;

UINT uiServerPort;//服务端的IP和Port

GetDlgItemText(IDC_EDIT_SERVER_IP, strServerIP);

uiServerPort = GetDlgItemInt(IDC_EDIT_SERVER_PORT);

if (!m_Pconnect->Connect(strServerIP, uiServerPort))

{

MessageBox(L"连接服务端失败");

return;

}

连接成功说明一个客户端加入房间

CString strEnterRoom = L"enter";

m_Pconnect->Send(strEnterRoom, strEnterRoom.GetLength() + 100);

m_bEnterRoom = TRUE;

界面的改变

GetDlgItem(IDC_BUTTON_ENTER_ROOM)->EnableWindow(FALSE);

GetDlgItem(IDC_BUTTON_LEAVE_ROOM)->EnableWindow(TRUE);

GetDlgItem(IDC_BUTTON_SEND)->EnableWindow(TRUE);

((CEdit*)GetDlgItem(IDC_EDIT_SEND_MESSAGE))->SetReadOnly(FALSE);

(4)、离开房间功能实现

CString strleaveRoom = L"leave";

m_Pconnect->Send(strleaveRoom, strleaveRoom.GetLength() + 100);

m_bEnterRoom = FALSE;

GetDlgItem(IDC_BUTTON_ENTER_ROOM)->EnableWindow(TRUE);

GetDlgItem(IDC_BUTTON_LEAVE_ROOM)->EnableWindow(FALSE);

GetDlgItem(IDC_BUTTON_SEND)->EnableWindow(FALSE);

((CEdit*)GetDlgItem(IDC_EDIT_SEND_MESSAGE))->SetReadOnly(TRUE);

((CEdit*)GetDlgItem(IDC_EDIT_SERVER_PORT))->SetReadOnly(FALSE);

((CEdit*)GetDlgItem(IDC_EDIT_SERVER_IP))->SetReadOnly(FALSE);

(5)、发送消息功能实现

发送消息给客户端

// TODO: 在此添加控件通知处理程序代码

CString strMsg;

GetDlgItemText(IDC_EDIT_SEND_MESSAGE, strMsg);

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

SetDlgItemText(IDC_EDIT_SEND_MESSAGE, L"");//将文本框清空方便下次输入

(6)、OnPendingRead函数实现

接收从客户端分发的消息

TCHAR buff4096;

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

if (nRead == SOCKET_ERROR)

{

return;

}

buffnRead = L'\0';

CString charMsg(buff);

CString alMsg;

GetDlgItemText(IDC_EDIT_CHAT_MESSAGE, alMsg);

SetDlgItemText(IDC_EDIT_CHAT_MESSAGE, alMsg + L"\r\n" + charMsg);

4、最终运行结果:

相关推荐
一个向上的运维者17 分钟前
Kubernetes 网络三部曲:CNI、kube-proxy 与 CoreDNS 是如何协作的?
网络·容器·kubernetes
2301_8150910143 分钟前
TCP 并发服务器模型:4 种 IO 模型完整梳理
服务器·网络·tcp/ip
斑马1391 小时前
Linux软件编程学习笔记(十二)——TCP并发服务器模型
java·服务器·网络
HugoStudio_SWAN1 小时前
洛谷 P1420 / P1179 / B4262 最长连号、数字统计与词频统计——统计的三种面孔
c++·学习·程序人生·算法
学着改变2751 小时前
2026便携式超声波流量计性能白皮书 户外巡检适用性横评
大数据·网络·人工智能·科技·产品运营·量子计算
rcms152702692182 小时前
Novellus Systems 02-033134-00晶圆底座加热器
网络
马立杰2 小时前
IE241210_路由安全技术(三层安全)
网络·安全
raindayinrain2 小时前
c++并发
c++
马立杰2 小时前
IE241211_路由安全技术(三层安全)
网络·安全·智能路由器
j7~2 小时前
【C++】智能指针的使用及其原理--详解
c++·c++11·内存泄漏·智能指针·raii·boost智能指针