MFC网络通信 用套接字 实现简单收发信息

我是用vs2013编写的。

一,建客户端项目

打开vs,新建对话框项目,勾选套接字

点击完成。

接下来,修改对话框界面

增加两个EDIT控件,上面的ID是IDC_HIST,多行,只读,无水平滚动条 ,有垂直滚动条。下面的ID是IDC_INPUT,其他不做改变。增加一个按钮控件,ID是IDC_BUTTON1,文字为连接。OK按钮文字修改为发送(&s)

增加一个类,可以点击项目菜单添加类ConnectSocket,基类是CSocket。

代码实现:

在ClientDlg.h文件添加:

#include "ConnectSocket.h"

	CConnectSocket m_sock;


 

在 BOOL CClientDlg::OnInitDialog()函数下添加如下代码:

	CDialogEx::OnInitDialog();
	m_sock.Create(); 
	if (!m_sock.Connect(_T("192.168.0.8"), 8118))//此处的IP地址记得写成自己电脑的IP
	{
		//连接服务器端运行的主机IP地址
		/*CString str;
		str.Format(_T("连接失败:%d"), GetLastError());
		AfxMessageBox(str);*/
		LPVOID lpMsgBuf;
		FormatMessage
			(
			FORMAT_MESSAGE_ALLOCATE_BUFFER | //返回一个已分配的内存
			FORMAT_MESSAGE_FROM_SYSTEM |  //系统消息
			FORMAT_MESSAGE_IGNORE_INSERTS, //无视插入信息
			NULL,
			GetLastError(),
			0, //默认语言
			(LPTSTR)&lpMsgBuf, //错误信息指针
			0,
			NULL
			);
		MessageBox((LPCTSTR)lpMsgBuf, NULL, MB_OK | MB_ICONINFORMATION);
		LocalFree(lpMsgBuf);//释放内存

	}
	else
	{
		CString sockStr;
		UINT port;
		CString str;
		m_sock.GetSockName(sockStr,port);
		str.Format(_T("客户端%s:%u"), sockStr, port);

		SetWindowText(str); //设置对话框的标题 
	}
..........

 为发送按钮添加代码:

	// TODO:  在此添加控件通知处理程序代码
	CString szText;
	int len;
	GetDlgItemText(IDC_INPUT, szText);
	
	len = szText.GetLength()*2;
	if (m_sock.Send(szText, len) == len) 
	{
		CEdit *pEdit = (CEdit*)GetDlgItem(IDC_HIST);
		pEdit->SetSel(pEdit->GetWindowTextLength(), -1);
		pEdit->ReplaceSel(_T("\n你对所有人说:\r\n") + szText + "\r\n");
	}
	else
	{
		MessageBox(_T("发送失败"), _T("警告"), MB_OK);
	}

//	CDialogEx::OnOK();

在对话框双击连接按钮,为连接按钮添加代码:

void CClientDlg::OnBnClickedButton1()
{
	// TODO:  在此添加控件通知处理程序代码
//	m_sock.Create();
	if (!m_sock.Connect(_T("192.168.0.8"), 8118))//此处的IP地址记得写成自己电脑的IP
	{
		//连接服务器端运行的主机IP地址
		CString str;
		//str.Format(_T("连接失败:%d"), GetLastError());
		LPVOID lpMsgBuf;
		FormatMessage
			(
			FORMAT_MESSAGE_ALLOCATE_BUFFER | //返回一个已分配的内存
			FORMAT_MESSAGE_FROM_SYSTEM |  //系统消息
			FORMAT_MESSAGE_IGNORE_INSERTS, //无视插入信息
			NULL,
			GetLastError(),
			0, //默认语言
			(LPTSTR)&lpMsgBuf, //错误信息指针
			0,
			NULL
			);
		MessageBox((LPCTSTR)lpMsgBuf, NULL, MB_OK | MB_ICONINFORMATION);
		LocalFree(lpMsgBuf);//释放内存
		//AfxMessageBox(str);
	}

}

ConnectSocket.h文件添加:

virtual	void OnReceive(int nErrorCode);

 ConnectSocket.cpp添加:

void CConnectSocket::OnReceive(int nErrorCode)
{
	// TODO: Add your specialized code here and/or call the base class
	char s[2048];
	int nLen = Receive(s, sizeof(s)-2);
	if (nLen <= 0)
		return;
	s[nLen] = 0;
	s[nLen+1] = 0;
	CWnd* pWnd = AfxGetMainWnd();
	CEdit* pEdit = (CEdit*)pWnd->GetDlgItem(IDC_HIST);
	pEdit->SetSel(pEdit->GetWindowTextLength(), -1);
	CString cstr((wchar_t*)s);
	pEdit->ReplaceSel(cstr);

	CSocket::OnReceive(nErrorCode);

为确定、取消按钮添加代码:

void CServerDlg::OnBnClickedCancel()
{
	// TODO:  在此添加控件通知处理程序代码
	m_sock.Close();
	CDialogEx::OnCancel();
}

客户端代码完成。

服务器端:新建Server对话框项目,勾选套接字。

对话框界面,

添加一个EDIT控件,ID是IDC_TEXT1,多行,只读,无水平滚动条,有垂直滚动条

添加ClientSocket类,基类Socket。声明函数,    

	virtual void OnReceive(int nErrorCode);
	virtual void OnClose(int nErrorCode);

代码实现:

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

#include "stdafx.h"
#include "Server.h"
#include "ClientSocket.h"
#include "resource.h"

extern CServerApp theApp;

// CClientSocket

CClientSocket::CClientSocket()
{
}

CClientSocket::~CClientSocket()
{
}


// CClientSocket 成员函数
extern CServerApp theApp;

void CClientSocket::OnReceive(int nErrorCode)
{
	// TODO: Add your specialized code here and/or call the base class
	char s[2084];
	int nLen;
		nLen= Receive(s, sizeof(s)-2);
	if (nLen<0)
		return;
	s[nLen] = 0;
	s[nLen+1] = 0;

	CString szIP;
	UINT nPort;
	GetPeerName(szIP, nPort);
	CString str;
	str.Format(_T("%s-%u对所有人说:\r\n%s\r\n"), szIP, nPort, s);
	CEdit *pEdit = (CEdit*)theApp.m_pMainWnd->GetDlgItem(IDC_TEXT1);
	pEdit->SetSel(pEdit->GetWindowTextLength(), -1);
	pEdit->ReplaceSel(str + "\r\n");


	CPtrList& list = theApp.m_list;
	POSITION pos = list.GetHeadPosition();
	while (pos)
	{
		//将一个客户端发来的聊天文字,群发给所有其他客户端
		CClientSocket* pSock = (CClientSocket*)list.GetAt(pos);
		//不对刚发出的聊天文字的客户端转发
		if (pSock != this)
			pSock->Send(str, str.GetLength()*2);
		list.GetNext(pos);
	}

	CSocket::OnReceive(nErrorCode);
}
void CClientSocket::OnClose(int nErrorCode) //用于检测某个客户端是否断开了连接
{
	// TODO: Add your specialized code here and/or call the base class
	//将与客户端断开连接的CClientSocket对象地址从链表中移除
	CPtrList &list = theApp.m_list;
	POSITION pos = list.GetHeadPosition();
	while (pos)
	{
		if (list.GetAt(pos) == this)
		{
			list.RemoveAt(pos);
			break;
		}
		list.GetNext(pos);
	}
	//清理对象占用的堆空间
	delete this;


	CSocket::OnClose(nErrorCode);
}

 添加ListenSocket,基类Socket,在头文件 声明函数:    virtual void OnAccept(int nErrorCode);

#pragma once

// CListenSocket 命令目标

class CListenSocket : public CSocket
{
public:
	CListenSocket();
	virtual ~CListenSocket();
	virtual void OnAccept(int nErrorCode);
};


代码实现:

// CListenSocket 成员函数
void CListenSocket::OnAccept(int nErrorCode)
{
	// TODO: Add your specialized code here and/or call the base class

	//新建一个CClientSocket
	CClientSocket *pSock = new CClientSocket;
	if (Accept(*pSock))
		theApp.m_list.AddTail(pSock);
	else
		delete pSock;

	CSocket::OnAccept(nErrorCode);
}

在server.cpp添加代码:

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

在ServerDlg.h添加:

#include "ListenSocket.h"
class CServerDlg : public CDialogEx
{
// 构造
public:
	CServerDlg(CWnd* pParent = NULL);	// 标准构造函数
	CListenSocket m_sock;//添加CListenScoket类型的成员变量
..........

在ServerDlg.cpp 添加代码:

BOOL CServerDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();
	if (m_sock.Create(8118))
		m_sock.Listen();
	else
	{
		CString str;
		str.Format(_T("Socket Create Error.%d"), GetLastError());
		AfxMessageBox(str);
	}


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

 

为取消按钮添加代码:

void CServerDlg::OnBnClickedCancel()
{
	// TODO:  在此添加控件通知处理程序代码
	m_sock.Close();
	CDialogEx::OnCancel();
}

 到此代码差不多了,字符串长度乘2是因为宽字符实际占两个字节。

可以多客户端和服务器连接通信。

 参考:《MFC网络通信》Part 2 简单TCP通信_梁的博客-CSDN博客_mfc tcp通信 https://blog.csdn.net/sinat_24206709/article/details/50936127

有一点改进:MFC EDIT控件最多容纳30000个字符, socket 网络通信连续接收程序代码_ywqb95的博客-CSDN博客

  • 3
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值