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

2023-11-11


在这里插入图片描述

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.
如有问题,欢迎交流,及时解决是最好的方案。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • IE10 上的 WebSocket 出现 SecurityError

    我目前正在 IE10 在 Windows 8 上 下开发一个网站 使用 JavaScript 中的 WebSockets 它在 Firefox 18 和 Chrome 25 下运行良好 但在 IE10 上建立连接时出现 SecurityEr
  • phantomjs 支持 Bayeux 或 WebSockets 吗?

    只是简单的问题 因为我在文档中没有找到任何参考资料 只是一个简单的答案 PhantomJS 1 x 不支持 但 PhantomJS 2 确实支持 websockets PhantomJS 2 0 0 的 Modernizr 输出
  • 在 Firefox 或我的代理中禁用 websocket

    我已将 Firefox 配置为使用我的 http 和 https 代理 是的 我自己编写代理代码 因此我可以完全控制代理 您可能知道 无法再通过 about config 在 Firefox 中禁用 WebSocket 我正在寻找一种轻量级
  • WebSocket - Safari 9 - 标头值中的 UTF-8 序列无效

    我正在创建一个在 Chrome 版本 47 0 2526 106 64 位 中工作的 WebSocket 但在 Safari 版本 9 0 2 11601 3 9 上失败 错误是Invalid UTF 8 sequence in heade
  • 简单的 Perl websocket 客户端

    我正在尝试用 Perl 编写一个简单的 websocket 客户端 use Protocol WebSocket Client my client Protocol WebSocket gt new url gt ws myserver p
  • Python Selenium webdriver 可以使用 websocket 吗?

    我有兴趣使用带有 websockets 的 python webdriver 来控制 firefox 首先是本地控制 然后是远程控制 我在谷歌上没有找到很多文档或示例 尽管有一些证据表明它是可能的 例如http blog imanel or
  • 使用WebSocket上传大文件

    我正在尝试使用 WebSocket API 上传大文件 至少 500MB 最好达到几 GB 问题是我不知道如何编写 发送文件的这一部分 释放所使用的资源 然后重复 我希望我可以避免使用 Flash Silverlight 之类的东西 目前
  • WebSocket 和纯 TCP 之间的根本区别是什么?

    我读过关于WebSockets http en wikipedia org wiki Web Sockets我想知道为什么浏览器不能像任何其他桌面应用程序一样简单地打开简单的 TCP 连接并与服务器通信 为什么可以通过 websocket
  • 使用 SPIFFS 加载文件时出现问题 (ERR_CONTENT_LENGTH_MISMATCH)

    好吧 这两天我一直在研究这个问题 但我仍然觉得我一无所获 我最近开始使用SPIFFS 文件系统 for Arduino开发于呼扎 ESP8266像FSBrowser ino例如 虽然它在分离代码方面非常出色 但随着我的代码不断增长 它在稳定
  • 为什么我的 wss://(基于 SSL/TLS 的 WebSockets)连接立即断开而不给出任何错误?

    将此发布给遇到同样问题的其他人 我当时正在开发一个浏览器客户端 它使用 stanza io 连接到 XMPP 服务器 在我的例子中是 Prosody 我默认使用 wss 连接 在开发过程中的某个时刻 我的客户端根本无法连接 它会立即无提示地
  • Websocket 在客户端返回 500,在服务器返回 101

    我们尝试使用 nginx ingress 控制器在 Kubernetes 集群上实现 WebSocket 入口 yaml apiVersion extensions v1beta1 kind Ingress metadata annotat
  • Websocket、Angular 2 和 JSON Web 令牌身份验证

    我的 Angular 2 应用程序 用打字稿编码 有一个简单的身份验证方案 用户登录 服务器返回 JSON Web 令牌 JWT abc123 在每次 API 调用时 应用程序都会将 JWT 发送到Authorization header
  • WebSocket 库 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我想在 Linux 上使用 C 访问 WebSocket API 我见过不同的图书馆 比如libweb
  • 通过 WebSocket 发送 ArrayBuffer 的子段而不进行复制

    我正在填充一个ArrayBuffer与要通过发送的数据WebSocket 数据具有可变大小 因此在序列化时我动态扩展ArrayBuffer如所须 然而 当序列化过程完成时 我经常在缓冲区末尾有未使用的空间 我不想发送这些空间 可以将所需部分
  • WebSocket 握手:意外响应代码:404

    正在编写我的第一个 websocket 程序并且正在得到 WebSocket 握手 意外响应代码 404 加载网页时出错 我使用的是 JDK 1 7 和 jboss 8 wildfly8 0 有人可以帮忙吗 window onload in
  • GO Websocket 向所有客户端发送消息

    这段代码一切正常 为了更好的阅读而缩短了它 When Client1向服务器发送请求 服务器立即响应他 但是 其他客户端看不到响应消息 所以我想更进一步 当客户端向服务器发送请求时 服务器会响应所有客户端 以便所有客户端都可以看到该消息 我
  • ServerEndpoint 和 web.xml

    我有一些 Soap REST servlet 现在还有一个 WebSocket ServerEndpoint game public class WebSocketgame 我有下一个麻烦 如果 web xml 存在 WebSocket 不
  • Tyrus WebSockets (Java) - 如何设置客户端本地 IP 地址

    使用 WebSockets Tyrus 时有没有办法指定本地 IP 地址和端口 我正在寻找你可以用完整的 4 个参数构造函数做的同样的事情Socket http docs oracle com javase 6 docs api java
  • 允许在 Google 计算引擎 (GCE) 中使用 WebSocket

    我正在使用计算引擎 GCE 通过 Socket IO Node js 运行我的套接字服务器 它仅适用于轮询 当我尝试使用网络客户端时 我收到以下错误代码 WebSocket connection to ws myapp socket app
  • webpack-dev-server 中的代理 websockets 连接

    是否可以在 webpack 开发服务器中代理 websocket 连接 我知道如何将常规 HTTP 请求代理到另一个后端 但它不适用于 websockets 大概是因为代理配置中的目标以 http 开头 webpack dev server

随机推荐

  • 线程池ThreadPoolExecutor源码解析

    参考视频 首先回顾一下创建线程等的三种方式 第一个是直接继承Thread类 重写run方法 这个其实内部也是继承了Runnable接口重写run方法 比如 public class MyThread extends Thread Overr
  • oracle查看数据文件大小,路径及修改大小

    查看数据文件占用大小使用大小 select b file id 文件ID号 b tablespace name 表空间名 b bytes 1024 1024 M 字节数 b bytes sum nvl a bytes 0 1024 1024
  • json11库的使用

    JSON JavaScript Object Notation 是一种轻量级的文本数据交换格式 易于让人阅读 同时也易于机器解析和生成 尽管JSON是Javascript的一个子集 但JSON是独立于语言的文本格式 并且采用了类似于C语言家
  • echarts图表的label太长解决办法

    如图 这个echarts图标的y轴label文字因为太长显示不全 这时我们可以选择使用formatter换行显示 具体代码如下 yAxis type category data 火灾 洪涝 急救 消防 公安 axisLabel format
  • Angular 下的 function

    angular lowercas 将指定的字符串转换为小写的 Usage 使用方法 angular lowercase string Arguments Param Type Details string string 字符串转换成小写 R
  • c语言二叉树链式存储,二叉树链式存储基本操作(C语言)

    1 二叉链的定义 LinkBinTree h文件 二叉树结点结构 typedef struct binnode int data struct binnode lchild struct binnode rchild BinNode 二叉树
  • Host is not allowed to connect to this MySQL server解决方法

    这个错误 其实就是我们安装的MySQL不允许远程登录 解决方法如下 1 在装有MySQL的机器上登录MySQL mysql u root p密码 执行use mysql select host from user where user ro
  • mongodb的MapReduce幂等性

    习惯用MapReduce来做mongodb的聚合 这一次遇到一点小问题 原数据如下 使用一个简单的MapReduce来验证一下数据 map function emit clientKey this clientKey dtime this
  • IDEA中SpringBoot启动错误无法加载主类

    1 项目里面 idea文件 删除 重启idea mvn claean install
  • MiniGUI 自定义控件教程7

    接着上次的教程继续 这次给大家介绍的是界面美观的进度条控件 它功能上和MiniGUI原有的进度条控件 CTRL PROGRESSBAR 是一样的 其实进度条也就是那些功能 哪还能整出别点什么花样哦 一 功能确定 1 要具有MiniGUI原有
  • ORACLE等待事件类型【Classes of Wait Events】

    每一个等待事件都属于某一类 下面给出了每一类等待事件的描述 Every wait event belongs to a class of wait event The following list describes each of the
  • 深入理解字节对齐

    C语言 字节对齐 基础知识了解 一 操作系统位数 CPU位数 指令集 1 操作系统 32 bit x86 和64 bit x64 1 位数 2 64 bit 2 处理器CPU位数 3 CPU指令集 4 寄存器 5 关系 6 计算机字长 机器
  • 百度智能云X英伟达直播实录超级AI计算机X-MAN技术

    GPU进入数据中心约有8 10年 这些年内 GPU显存的容量 GPU P2P带宽 GPU性能都在不断提升 据不完全统计 每年GPU显存大约有一倍的变化 P2P带宽有1 5倍到2倍的变化 而且性能变化更多 由于性能的变化 会引起GPU功耗的变
  • Android中解决第三方库重复引用的问题

    如果app中引入了一个新的第三方库 并且这个新库中引入了原本已经引入的另一个库 结果导致重复引用 编译就会报错 如何解决呢 方法是使用exclude排除重复的库 举例 假设新引入的第三方库是 com xiboliya mylib netto
  • JAVA中的类

    一 什么是类 概念 类就是某些具备某些共同特征的实体的集合 它是一种抽象的数据类型 它是对所具有相同特征实体的抽象 在面向对象的程序设计语言中 类是对一类 事物 的属性与行为的抽象 类可以理解为一个模板 它描述一类对象的行为和状态 举个例子
  • 【Linux安全】chattr命令锁定账户敏感文件

    有时候你发现用root权限都不能修改某个文件 大部分原因是曾经用chattr命令锁定该文件了 chattr命令的作用很大 其中一些功能是由Linux内核版本来支持的 不过现在生产绝大部分跑的linux系统都是2 6以上内核了 通过chatt
  • jQuery 入门教程(9):终止动画

    jQuery的使用stop 方法在动画结束之前停止动画 基本语法如下 selector stop stopAll goToEnd 可选参数stopAll 指明是否同时清除 动画队列 缺省为false 意味着只停止当前活动的动画 之后的动画则
  • retrofit合理的处理response

    OKHttp retrofit 有时候使用起来确实会受到一些局限 比如 处理response的加解密 处理response的返回的字段与本地封装的不一样 又不能改本地的字段 所以需要对返回的JSON进一步处理 别名的方式 处理respons
  • 【mysql】云服务器被攻击,数据库以及数据都被删除如何通过binlog日志恢复

    前言 小编买了一台阿里云服务器 然后通过docker 部署了mysql 然后用了一段时间突然发现数据都没有了 然后就排查问题 发现是被攻击了 如下图 you must pay 0 26BTC 怒了 好多钱呢 如果有同样的问题 可以参考此博客
  • MFC实现socket网络通信--主机与服务器之间传送数据

    MFC实现socket网络通信 模拟主机与服务器之间传送数据 MFC实现socket网络通信 1 新建MFC应用程序 2 创建服务端窗口界面 3 写服务器代码 4 创建客户端窗口界面 5 客户端代码部分 6 开始调试 7 小结 MFC实现s