MFC实现socket网络通信--主机与服务器之间传送数据


在这里插入图片描述

MFC实现socket网络通信

由于实验课没有好好听老师前面的实验步骤,外加没有学习过MFC,所以我决定好好实现这个网络模拟通信过程实验,如有不当之处,还请大家批评指教。
我这边用的是vs2012,用vc6.0实现也可以,内容本质上都一样的。
文章最后有我的源码,需要的同学可以直接下载运行比较贴心,哈哈。

1.新建MFC应用程序

1.1.MFC应用名为Server,解决方案名称这里改为了tcp编程
开始创建服务端应用程序

1.2需要改的地方我提一下,其他默认下一步
在这里插入图片描述
1.3勾选过后,就不需要我们自己去初始化windows的资源库了 ,“init”函数会自动帮我们初始化
自动初始化资源库
1.4选好直接点击完成。服务端应用程序创建完成。
选择类

1.5创建好的显示界面
服务端创建完成

2.创建服务端窗口界面

点击工具箱,出现控件

  1. 创建服务器基本界面,
    基本界面
  2. 更改静态文本框的内容,显示状态

在这里插入图片描述

在这里插入图片描述
3.同理改变Button1的名字,改成发送。

  1. 修改控件标识符,还是先点右键的属性,再找到工具箱的杂项,修改“ID”为IDC_ADDR。她下面修改的是服务器状态的控件标识符,同理修改按钮(发送)的控件标识符为IDC_SEND、将发送按钮上面的示例编辑框(小的)控件标识符修改为IDC_SENDTEXT,再将最大的示例编辑框的控件标识符修改为TEXT。这里只给一个修改例子,都一样的操作。
    在这里插入图片描述

  2. 调试运行

  3. 选中大的示例编辑框,点击右键,更改一些属性,使它能够显示多行、换行显示。找到行为,将Multiline改为Ture,显示多行;找到外观,将Auto VScroll改为true,显示换行。
    在这里插入图片描述
    外观,找到Vertical Scroll,显示滚动条改为True
    显示滚动条

  4. 调试一下,可以看到和4有点不一样,比4更完善。这里窗口部分就做好了
    在这里插入图片描述

3.写服务器代码

  1. 这里我先通过添加成员变量向导来添加变量,我们需要两个SOCKET套接字。在这里插入图片描述
    第一个是客户端的SOCKET套接字
    在这里插入图片描述
    同样的方法定义第二个。
    第二个是连接后返回的套接字
    在这里插入图片描述

  2. 同样的方法,定义一个计数的,表示多少个客户端连接。
    在这里插入图片描述

  3. 添加一个服务器ip地址变量
    在这里插入图片描述

  4. 定义一个变量去传进来客户端的ip
    在这里插入图片描述

  5. 查看添加的变量
    在这里插入图片描述
    拉到最后,能够看见1,2,3,4添加的变量
    在这里插入图片描述

  6. 用类向导添加自定义消息。右键点击类向导,进来点消息
    在这里插入图片描述

  7. 编写代码,这边步骤就不来了,关键地方我都有注释。这边可以看到有三个.cpp文件,我这里把代码全部复制过来,你们可以直接使用。也就是下面的8,9,10,11三步。

  8. 先找到三个源文件。这里提一下,每写好一部分程序,最好点Ctrl s保存。

在这里插入图片描述

  1. Server.cpp文件

// Server.cpp : 定义应用程序的类行为。
//

#include "stdafx.h"
#include "Server.h"
#include "ServerDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CServerApp

BEGIN_MESSAGE_MAP(CServerApp, CWinApp)
	ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()


// CServerApp 构造

CServerApp::CServerApp()
{
	// TODO: 在此处添加构造代码,
	// 将所有重要的初始化放置在 InitInstance 中
}


// 唯一的一个 CServerApp 对象

CServerApp theApp;


// CServerApp 初始化

BOOL CServerApp::InitInstance()
{
	CWinApp::InitInstance();

	if (!AfxSocketInit())
	{
		AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
		return FALSE;
	}


	// 创建 shell 管理器,以防对话框包含
	// 任何 shell 树视图控件或 shell 列表视图控件。
	CShellManager *pShellManager = new CShellManager;

	// 激活“Windows Native”视觉管理器,以便在 MFC 控件中启用主题
	CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));

	// 标准初始化
	// 如果未使用这些功能并希望减小
	// 最终可执行文件的大小,则应移除下列
	// 不需要的特定初始化例程
	// 更改用于存储设置的注册表项
	// TODO: 应适当修改该字符串,
	// 例如修改为公司或组织名
	SetRegistryKey(_T("应用程序向导生成的本地应用程序"));

	CServerDlg dlg;
	m_pMainWnd = &dlg;
	INT_PTR nResponse = dlg.DoModal();
	if (nResponse == IDOK)
	{
		// TODO: 在此放置处理何时用
		//  “确定”来关闭对话框的代码
	}
	else if (nResponse == IDCANCEL)
	{
		// TODO: 在此放置处理何时用
		//  “取消”来关闭对话框的代码
	}
	else if (nResponse == -1)
	{
		TRACE(traceAppMsg, 0, "警告: 对话框创建失败,应用程序将意外终止。\n");
		TRACE(traceAppMsg, 0, "警告: 如果您在对话框上使用 MFC 控件,则无法 #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。\n");
	}

	// 删除上面创建的 shell 管理器。
	if (pShellManager != NULL)
	{
		delete pShellManager;
	}

	// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
	//  而不是启动应用程序的消息泵。
	return FALSE;
}


  1. ServerDlg.cpp

// ServerDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "Server.h"
#include "ServerDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// 对话框数据
	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CServerDlg 对话框



CServerDlg::CServerDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CServerDlg::IDD, pParent)
	, n(0)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CServerDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CServerDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_MESSAGE(WM_SOCKET, &CServerDlg::OnSocket)
	ON_MESSAGE(WM_SOCKET,&CServerDlg::OnSocket)
	ON_BN_CLICKED(IDC_SEND, &CServerDlg::OnBnClickedSend)
END_MESSAGE_MAP()


// CServerDlg 消息处理程序

BOOL CServerDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	//1.初始化网络套接字库。勾选了,已经初始化了。
	//2.创建套接字
	s=socket(AF_INET,SOCK_STREAM,0);
	//3.处理地址---网络字节顺序
	addr.sin_family=AF_INET;
	addr.sin_port=htons(520);
	addr.sin_addr.S_un.S_addr=INADDR_ANY;
	//4.绑定端口和ip
	bind(s,(sockaddr *)&addr,sizeof(addr));
	listen(s,5);
	//设置套接字为异步套接
	WSAAsyncSelect(s,this->m_hWnd,WM_SOCKET,FD_ACCEPT|FD_READ);
	//把聊天的TEXT设置为不可修改
	GetDlgItem(IDC_TEXT)->EnableWindow(false);
	//修改服务器状态
	GetDlgItem(IDC_ADDR)->SetWindowTextA("服务器监听已经启动!");
	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CServerDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CServerDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CServerDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}




	afx_msg LRESULT CServerDlg::OnSocket(WPARAM wParam,LPARAM lparam)
	{
		//异步套接字处理
		CString str;
		char cs[100]="";
		switch(lparam)
		{
		case FD_ACCEPT:
			{
				int length=sizeof(addr1);
				//接收客户端的请求
				s1=accept(s,(sockaddr*)&addr1,&length);
				n=n+1;
				str.Format("有%d个客户端已经连接上了",n);
				str+=inet_ntoa(addr1.sin_addr);
				str+="\r\n登录\r\n";
				GetDlgItem(IDC_TEXT)->SetWindowTextA(str);

			}
			break;
		case FD_READ:
			{
				CString num="";
				recv(s1,cs,100,0);

				GetDlgItem(IDC_TEXT)->GetWindowTextA(num);
				num+="\r\n";
				num+=("客户端:");
				num+=(LPTSTR)cs;
				GetDlgItem(IDC_TEXT)->SetWindowText(num);
			}
			break;
		}
		return 0;
	}

	void CServerDlg::OnBnClickedSend()
	{
		// TODO: 在此添加控件通知处理程序代码
		CString str="";//接受控件中的值
		GetDlgItem(IDC_SENDTEXT)->GetWindowTextA(str);
		if(str=="")//不能发送空消息
		{
			MessageBox("消息不能为空");
		}else
		{
			//发消息给客户端
			//成功发送
			if(send(s1,str.GetBuffer(1),str.GetLength(),0)!=SOCKET_ERROR)
			{
				GetDlgItem(IDC_TEXT)->GetWindowTextA(str);
				str+="消息已经发送到客户端!\r\n";
				GetDlgItem(IDC_TEXT)->SetWindowTextA(str);
			}else//发送失败
			{
				GetDlgItem(IDC_TEXT)->SetWindowTextA("发送消息失败!\r\n");
			}


	}
	}
  1. stdafx.cpp

// stdafx.cpp : 只包括标准包含文件的源文件
// Server.pch 将作为预编译头
// stdafx.obj 将包含预编译类型信息

#include "stdafx.h"



  1. 至此,服务器端已经完成。运行显示如下
    在这里插入图片描述

4、创建客户端窗口界面

  1. 和创建服务器端差不多,这里就只展示了布局方面大家随意即可。命名为Client。
    在这里插入图片描述

  2. 这边更改一些控件标识符
    在这里插入图片描述

  3. 对信息框进行设置多行显示、换行、滚动查看
    在这里插入图片描述

  4. 这里外观就ok了。我们再设置套接字s,再设置个地址变量addr打开添加变量:
    在这里插入图片描述

在这里插入图片描述

5、客户端代码部分

  1. 解决方案->Client->源文件->三个.cpp文件
    在这里插入图片描述
  2. 修改Client.cpp文件

// Client.cpp : 定义应用程序的类行为。
//

#include "stdafx.h"
#include "Client.h"
#include "ClientDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CClientApp

BEGIN_MESSAGE_MAP(CClientApp, CWinApp)
	ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()


// CClientApp 构造

CClientApp::CClientApp()
{
	// TODO: 在此处添加构造代码,
	// 将所有重要的初始化放置在 InitInstance 中
}


// 唯一的一个 CClientApp 对象

CClientApp theApp;


// CClientApp 初始化

BOOL CClientApp::InitInstance()
{
	CWinApp::InitInstance();

	if (!AfxSocketInit())
	{
		AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
		return FALSE;
	}


	// 创建 shell 管理器,以防对话框包含
	// 任何 shell 树视图控件或 shell 列表视图控件。
	CShellManager *pShellManager = new CShellManager;

	// 激活“Windows Native”视觉管理器,以便在 MFC 控件中启用主题
	CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));

	// 标准初始化
	// 如果未使用这些功能并希望减小
	// 最终可执行文件的大小,则应移除下列
	// 不需要的特定初始化例程
	// 更改用于存储设置的注册表项
	// TODO: 应适当修改该字符串,
	// 例如修改为公司或组织名
	SetRegistryKey(_T("应用程序向导生成的本地应用程序"));

	CClientDlg dlg;
	m_pMainWnd = &dlg;
	INT_PTR nResponse = dlg.DoModal();
	if (nResponse == IDOK)
	{
		// TODO: 在此放置处理何时用
		//  “确定”来关闭对话框的代码
	}
	else if (nResponse == IDCANCEL)
	{
		// TODO: 在此放置处理何时用
		//  “取消”来关闭对话框的代码
	}
	else if (nResponse == -1)
	{
		TRACE(traceAppMsg, 0, "警告: 对话框创建失败,应用程序将意外终止。\n");
		TRACE(traceAppMsg, 0, "警告: 如果您在对话框上使用 MFC 控件,则无法 #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。\n");
	}

	// 删除上面创建的 shell 管理器。
	if (pShellManager != NULL)
	{
		delete pShellManager;
	}

	// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
	//  而不是启动应用程序的消息泵。
	return FALSE;
}


  1. 修改ClientDlg.cpp

// ClientDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "Client.h"
#include "ClientDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// 对话框数据
	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CClientDlg 对话框



CClientDlg::CClientDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CClientDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CClientDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CClientDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_MESSAGE(WM_SOCKET,&CClientDlg::OnSocket)
	ON_BN_CLICKED(IDC_CONNECT, &CClientDlg::OnBnClickedConnect)
	ON_BN_CLICKED(IDC_SEND, &CClientDlg::OnBnClickedSend)
	ON_EN_CHANGE(IDC_SENDTEXT, &CClientDlg::OnEnChangeSendtext)
	ON_EN_CHANGE(IDC_ADR, &CClientDlg::OnEnChangeAdr)
END_MESSAGE_MAP()


// CClientDlg 消息处理程序

BOOL CClientDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	//设置控件属性
	GetDlgItem(IDC_TEXT)->EnableWindow(false);
	GetDlgItem(IDC_SENDTEXT)->EnableWindow(false);
	GetDlgItem(IDC_SEND)->EnableWindow(false);
	s=socket(AF_INET,SOCK_STREAM,0);
	WSAAsyncSelect(s,this->m_hWnd,WM_SOCKET,FD_READ);
	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CClientDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CClientDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CClientDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

afx_msg LRESULT CClientDlg::OnSocket(WPARAM wParam,LPARAM lParam)
{
	char cs[100]="";
	if(lParam==FD_READ)
	{
		CString num="";
		recv(s,cs,100,0);
		GetDlgItem(IDC_TEXT)->GetWindowTextA(num);
		num+="\r\n服务器";
		num+=(LPTSTR)cs;
		GetDlgItem(IDC_TEXT)->SetWindowTextA(num);
	return 0;
}
}

void CClientDlg::OnBnClickedConnect()
{
	// TODO: 在此添加控件通知处理程序代码
	CString str,str1;//字符串,用来接收处理ip
	int port;//端口
	GetDlgItem(IDC_ADDR)->GetWindowTextA(str);
	GetDlgItem(IDC_PROT)->GetWindowTextA(str1);
	if(str==""||str1=="")
	{
		MessageBox("端口或服务器地址不能为NULL");
	}else
	{
		//转换为整型
		port=atoi(str1.GetBuffer(1));
		//ip地址处理
		addr.sin_family=AF_INET;
		addr.sin_port=ntohs(port);
		addr.sin_addr.S_un.S_addr=inet_addr(str.GetBuffer(1));
		GetDlgItem(IDC_TEXT)->SetWindowTextA("正在连接服务器..\r\n");
		//连接
	
		if(connect(s,(sockaddr *)&addr,sizeof(addr)))
		{
			GetDlgItem(IDC_TEXT)->GetWindowTextA(str);
			str += "连接服务器成功\r\n";
			GetDlgItem(IDC_TEXT)->SetWindowTextA(str);
			//控件状态修改下
			GetDlgItem(IDC_SENDTEXT)->EnableWindow(true);
			GetDlgItem(IDC_SEND)->EnableWindow(true);
			GetDlgItem(IDC_ADDR)->EnableWindow(false);
			GetDlgItem(IDC_PROT)->EnableWindow(false);
		}else
		{
			GetDlgItem(IDC_TEXT)->GetWindowTextA(str);
			str+="连接服务器失败!!!\r\n";
			GetDlgItem(IDC_TEXT)->SetWindowTextA(str);

		}
	}
}



void CClientDlg::OnBnClickedSend()
{
	// TODO: 在此添加控件通知处理程序代码
	CString str,str1;
	GetDlgItem(IDC_SENDTEXT)->GetWindowTextA(str);
	if(str=="")
	{
		MessageBox("消息发送不能为NULL");
	}else
	{
		send(s,str.GetBuffer(1),str.GetLength(),0);
		GetDlgItem(IDC_TEXT)->GetWindowTextA(str1);
		str1="\r\n";
		str1+=str;
		GetDlgItem(IDC_TEXT)->SetWindowTextA(str1);
	}



	
}


void CClientDlg::OnEnChangeSendtext()
{
	// TODO:  如果该控件是 RICHEDIT 控件,它将不
	// 发送此通知,除非重写 CDialogEx::OnInitDialog()
	// 函数并调用 CRichEditCtrl().SetEventMask(),
	// 同时将 ENM_CHANGE 标志“或”运算到掩码中。
	// TODO:  在此添加控件通知处理程序代码
}


void CClientDlg::OnEnChangeAdr()
{
	// TODO:  如果该控件是 RICHEDIT 控件,它将不
	// 发送此通知,除非重写 CDialogEx::OnInitDialog()
	// 函数并调用 CRichEditCtrl().SetEventMask(),
	// 同时将 ENM_CHANGE 标志“或”运算到掩码中。
	// TODO:  在此添加控件通知处理程序代码
}
  1. 修改stdafx.cpp

// stdafx.cpp : 只包括标准包含文件的源文件
// Client.pch 将作为预编译头
// stdafx.obj 将包含预编译类型信息

#include "stdafx.h"



  1. 至此,客户端与服务器已全部完成

6、开始调试

  • 完成界面
    在这里插入图片描述
  • 主机号输入127.0.0.1,作循环回路测试。当然也可以通过cmd->ipconfig来找到自己的本机ip地址,两种方法都行。
    这里端口号我设置的是520(服务器代码段中).这里端口号设置有个要求,必须是唯一端口号,即没有被其他应用占用,否则会显示失败。
  • 端口号设置,先找到服务器的ServerDlg.cpp文件
    在这里插入图片描述
  • 这里可以把端口号520换成其他了。10000以下的端口号会被计算机自己的程序占用。建议3000以上或其他都行,毕竟用于测试。

在这里插入图片描述

在这里插入图片描述
回车会把窗口关闭,点上面的按钮就行,不要点回车,切记!!

7、小结

  1. 为防止部分同学操作过程中可能会粗心大意,输错代码,我这里把我的文件打包了,需要的同学可以直接下载运行,贴心ya!!!

腾讯微云链接: link.
百度网盘链接(提起码:qj1r): link.
如有问题,欢迎交流,及时解决是最好的方案。

  • 59
    点赞
  • 207
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 49
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 49
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

毕竟是shy哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值