基于Socket的MFC网络编程

一、基于TCP协议的编程步骤

服务器端:

1. 加载套接字库(WSAStartup)

2. 创建用于监听的套接字(socket),然后将其绑定到本地SOCKADDR(bind),并将其设为监听模式(listen)

3. 等待客户请求的到来:一旦收到客户连接请求,返回一个对应该连接的套接字(accept)

4. 利用返回的套接字与客户端进行通信(recv/send)

5. 通信完毕,关闭套接字(closesocket)并终止套接字库的使用(WSACleanup)

	// 加载套接字库
	WSAData wsaData;
	if(0 != WSAStartup(MAKEWORD(1, 1), &wsaData))
	{
		return;
	}
	if(1 != LOBYTE(wsaData.wVersion) ||
	   1 != HIBYTE(wsaData.wVersion))
	{
		// 终止对套接字库的使用
		WSACleanup();
		return;
	}

	// 创建用于监听的套接字
	SOCKET sockListen = socket(AF_INET, SOCK_STREAM, 0);

	// 绑定监听套接字到某个本地地址信息结构体
	SOCKADDR_IN addrSrv;
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	addrSrv.sin_port = htons(6000);
	bind(sockListen, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));

	// 将监听套接字设为监听模式,准备接收客户请求
	listen(sockListen, 6);

	// 处理客户请求
	SOCKADDR_IN addrClient;
	int len = sizeof(SOCKADDR);
	while(1)
	{
		// 等待客户请求的到来
		// 每次接收到客户请求后,返回对应本次连接的套接字
		// 建立连接后,就可以使用返回的套接字与客户端进行通信了
		SOCKET sockSrv = accept(sockListen, (SOCKADDR *)&addrClient, &len);
		
		// 发送数据
		char sendBuf[100];
		sprintf(sendBuf, "Welcome %s to http://www.communication.org", inet_ntoa(addrClient.sin_addr));
		send(sockSrv, sendBuf, strlen(sendBuf) + 1, 0);

		// 接收数据
		char recvBuf[100];
		recv(sockSrv, recvBuf, sizeof(recvBuf), 0);
		printf("%s
", recvBuf);

		// 关闭本次连接的套接字
		closesocket(sockSrv);
	}

	// 终止对套接字库的使用
	WSACleanup();

客户端:

1. 加载套接字库(WSAStartup)

2. 创建用于通信的套接字(socket)

3. 向服务器发出连接请求(connect)

4. 利用已连接的套接字与服务器进行通信(send/recv)

5. 通信完毕,关闭套接字(closesocket)并终止套接字库的使用(WSACleanup)

	// 加载套接字库
	WSADATA wsaData;
	if(0 != WSAStartup(MAKEWORD(1, 1), &wsaData))
	{
		return;
	}
	if (1 != LOBYTE(wsaData.wVersion) ||
		1 != HIBYTE(wsaData.wVersion))
	{
		// 终止对套接字库的使用
		WSACleanup();
		return;
	}

	// 创建套接字
	SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);

	// 向服务器发出连接请求
	// 建立连接后,就可以利用请求套接字与服务器进行通信了
	SOCKADDR_IN addrSrv;
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	addrSrv.sin_port = htons(6000);
	connect(sockClient, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));

	// 接收数据
	char recvBuf[100];
	recv(sockClient, recvBuf, sizeof(recvBuf), 0);
	printf("%s
", recvBuf);

	// 发送数据
	send(sockClient, "This is TcpClient One.", strlen("This is TcpClient One.")+1, 0);

	// 关闭套接字,终止套接字库使用
	closesocket(sockClient);
	WSACleanup();

二、基于UDP协议的编程步骤

服务器端:

1. 加载套接字库(WSAStartup)

2. 创建用于通信的套接字(socket),然后将其绑定到本地SOCKADDR(bind)

3. 利用创建的套接字与客户端进行通信(recvfrom/sendto)

4. 通信完毕,关闭套接字(closesocket)并终止套接字库的使用(WSACleanup)

	// 加载套接字库
	WSAData wsaData;
	if(0 != WSAStartup(MAKEWORD(1, 1), &wsaData))
	{
		return;
	}
	if(1 != LOBYTE(wsaData.wVersion) ||
	   1 != HIBYTE(wsaData.wVersion))
	{
		// 终止对套接字库的使用
		WSACleanup();
		return;
	}


	// 创建套接字
	SOCKET sockSrv = socket(AF_INET, SOCK_DGRAM, 0);

	// 绑定套接字到某个本地地址信息结构体
	SOCKADDR_IN addrSrv;
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	addrSrv.sin_port = htons(6000);
	bind(sockSrv, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));

	// 等待并接收数据
	// 直接利用绑定到本地的套接字进行数据接收
	SOCKADDR_IN addrClient;
	int len = sizeof(SOCKADDR);
	char recvBuf[100];
	recvfrom(sockSrv, recvBuf, sizeof(recvBuf), 0,
		(SOCKADDR *)&addrClient, &len);
	printf("%s
", recvBuf);

	// 关闭套接字,并终止套接字库的使用
	closesocket(sockSrv);
	WSACleanup();

客户端:

1. 加载套接字库(WSAStartup)

2. 创建用于通信的套接字(socket)

3. 利用创建的套接字与服务器进行通信(sendto/recvfrom)

4. 通信完毕,关闭套接字(closesocket)并终止套接字库的使用(WSACleanup)

	// 加载套接字库
	WSAData wsaData;
	if(0 != WSAStartup(MAKEWORD(1, 1), &wsaData))
	{
		return;
	}
	if(1 != LOBYTE(wsaData.wVersion) ||
	   1 != HIBYTE(wsaData.wVersion))
	{
		// 终止对套接字库的使用
		WSACleanup();
		return;
	}

	// 创建套接字
	SOCKET sockClient = socket(AF_INET, SOCK_DGRAM, 0);

	// 直接利用创建的套接字向SOCKADDR指定的服务器发送数据
	SOCKADDR_IN addrSrv;
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	addrSrv.sin_port = htons(6000);
	sendto(sockClient, "Hello", strlen("Hello")+1, 0,
		(SOCKADDR *)&addrSrv, sizeof(SOCKADDR));

	// 关闭套接字,并终止套接字库的使用
	closesocket(sockClient);
	WSACleanup();

三、注意事项

编写基于socket网络应用程序时,需事先做到两件事:

1. 包含头文件:Winsock2.h

2. 添加依赖项:ws2_32.lib

基于TCP协议网络应用程序和基于UDP协议的网络应用程序的区别在于:

1. TCP服务器需要在接收到客户端连接请求后,才能与之通信;而UDP服务器直接利用绑定到本地的套接字等待接收数据,接收到数据后才知道客户端的地址信息

2. TCP客户端需要在与服务器建立链接后,才能与之通信;而UDP客户端直接利用绑定到本地的套接字向服务器发送数据,指定的服务器地址信息可以任意指定,因此不确定能不能被接收

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MFC(Microsoft Foundation Class)是微软公司提供的一个基于Windows的C++应用程序框架。MFC包含了许多类和函数库,可以帮助开发者更轻松地开发Windows应用程序。网络编程MFC框架中的一部分,通过MFC可以实现基于TCP或UDP协议的网络编程MFC中的网络编程主要依靠Windows Socket API来实现。Windows Socket API是Windows操作系统提供的一套网络编程接口,包括了TCP/IP协议栈以及与之相关的函数库和数据结构。MFC封装了Windows Socket API,提供了更加简单易用的网络编程接口。 以下是一个基于MFC的TCP客户端示例代码: ```cpp // 基于MFC的TCP客户端示例代码 #include "stdafx.h" #include "MFCNetworkProgramming.h" #include "MFCNetworkProgrammingDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CMFCNetworkProgrammingApp BEGIN_MESSAGE_MAP(CMFCNetworkProgrammingApp, CWinApp) ON_COMMAND(ID_HELP, &CWinApp::OnHelp) END_MESSAGE_MAP() // CMFCNetworkProgrammingApp 构造 CMFCNetworkProgrammingApp::CMFCNetworkProgrammingApp() { // TODO: add construction code here, // Place all significant initialization in InitInstance } // 唯一的 CMFCNetworkProgrammingApp 对象 CMFCNetworkProgrammingApp theApp; // CMFCNetworkProgrammingApp 初始化 BOOL CMFCNetworkProgrammingApp::InitInstance() { // 初始化 MFC 和通用控件 AfxEnableControlContainer(); // 创建对话框 CMFCNetworkProgrammingDlg dlg; m_pMainWnd = &dlg; INT_PTR nResponse = dlg.DoModal(); // 删除对话框对象 if (nResponse == IDOK) { // TODO: Place code here to handle when the dialog is // dismissed with OK } else if (nResponse == IDCANCEL) { // TODO: Place code here to handle when the dialog is // dismissed with Cancel } // 删除该应用程序的最上层窗口,除非该应用程序是使用 // Control Panel 来关闭的或者有其他窗口在等待退出。 return FALSE; } ``` 这是一个基本的MFC框架,它创建了一个对话框,并将其作为程序的主窗口。接下来我们需要在对话框中实现TCP客户端的功能。以下是一个基于MFC的TCP客户端示例代码: ```cpp // 基于MFC的TCP客户端示例代码 #include "stdafx.h" #include "MFCNetworkProgramming.h" #include "MFCNetworkProgrammingDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CMFCNetworkProgrammingDlg 对话框 CMFCNetworkProgrammingDlg::CMFCNetworkProgrammingDlg(CWnd* pParent /*=NULL*/) : CDialog(CMFCNetworkProgrammingDlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CMFCNetworkProgrammingDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_SERVER_IP, m_serverIP); DDX_Control(pDX, IDC_SERVER_PORT, m_serverPort); DDX_Control(pDX, IDC_DATA, m_data); } BEGIN_MESSAGE_MAP(CMFCNetworkProgrammingDlg, CDialog) ON_WM_PAINT() ON_WM_QUERYDRAGICON() //}}AFX_MSG_MAP ON_BN_CLICKED(IDC_CONNECT, &CMFCNetworkProgrammingDlg::OnBnClickedConnect) ON_BN_CLICKED(IDC_SEND, &CMFCNetworkProgrammingDlg::OnBnClickedSend) END_MESSAGE_MAP() // CMFCNetworkProgrammingDlg 消息处理程序 BOOL CMFCNetworkProgrammingDlg::OnInitDialog() { CDialog::OnInitDialog(); // 设置此对话框的图标。当应用程序主窗口不是对话框时, // 框架将自动执行此操作 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: Add extra initialization here return TRUE; // 除非将焦点设置到控件,否则返回 TRUE } // 如果添加了最小化按钮,则需要以下代码来绘制该图标。 // 对于使用文档/视图模型的 MFC 应用程序,这将由框架自动完成。 void CMFCNetworkProgrammingDlg::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 { CDialog::OnPaint(); } } //当用户拖动最小化窗口时系统调用此函数取得光标 //显示。 HCURSOR CMFCNetworkProgrammingDlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } void CMFCNetworkProgrammingDlg::OnBnClickedConnect() { // 创建套接字 m_socket.Create(); // 获取服务器地址和端口 CString strIP, strPort; m_serverIP.GetWindowText(strIP); m_serverPort.GetWindowText(strPort); // 连接服务器 if (m_socket.Connect(strIP, _ttoi(strPort)) == FALSE) { AfxMessageBox(_T("连接服务器失败")); } else { AfxMessageBox(_T("连接服务器成功")); } } void CMFCNetworkProgrammingDlg::OnBnClickedSend() { // 获取发送数据 CString strData; m_data.GetWindowText(strData); // 发送数据 if (m_socket.Send(strData, strData.GetLength()) == SOCKET_ERROR) { AfxMessageBox(_T("发送数据失败")); } else { AfxMessageBox(_T("发送数据成功")); } } ``` 以上代码实现了一个基于MFC的TCP客户端,用户可以在界面上输入服务器地址、端口和数据,然后点击连接按钮进行连接,点击发送按钮可以向服务器发送数据。需要注意的是,在实际使用中需要根据具体情况进行相应的修改和完善。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值