《MFC网络通信》Part 2 简单TCP通信

《MFC网络通信》Part 2 简单TCP通信                                                                                                                                          

一般TCP通信软件都分为服务器端客户端

TCP服务器端由一个侦听Socket和多个用于应答的Socket组成,每个应答Socket与客户端建立一对一的数据流通道。

客户端程序只包含一个链接Socket,它在成功连接服务器后与某一个应答Socket经行一对一的数据通信。

因此,我们需要创建两个程序,分别是服务器程序和客户端程序。分别命名为Server和Client。

第一步:创建Server服务器程序。

1、新建普通的MFC(exe)对话框程序,程序命名为Server,第二步中勾选Window Sockets

2、创建工程完毕后,记得查看stdafx.h中的预编译头文件,检查是否包括:

#include <afxsock.h><span style="white-space:pre">	</span>//MFC socket extensions
3、查看类视图中的CServerApp类中的函数InitInstance函数是否自动生成以下代码:
BOOL CServerApp::InitInstance()
{
	if (!AfxSocketInit())
	{
		AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
		return FALSE;
	}

	// Standard initialization
	// If you are not using these features and wish to reduce the size
	//  of your final executable, you should remove from the following
	//  the specific initialization routines you do not need.
……
4、在Server工程中创建一个CSocket类的派生类CListenSocket(Name中的1忽略掉):


5、同样的方法创建一个CSocket类的派生类CClientSocket。

6、在CServerApp类的头文件中添加一个指针链表类型的成员变量。

class CServerApp : public CWinApp
{
public:
	CPtrList m_list;//公有成员变量存储与客户端通信的CClientSocket对象的地址

……

7、在创建的CListenSocket类中添加 虚函数OnAccept,用于截获客户端的连接。

// CListenSocket member functions

#include "ClientSocket.h"
extern CServerApp theApp;

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);
}


8、在CClientSocket类中添加 虚函数OnReceive,用于截获客户端发来的网络数据。

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 = Receive(s,sizeof(s)-1);
	if(nLen<0)
		return ;
	s[nLen] = 0;

	CString szIP;
	UINT nPort;
	GetPeerName(szIP,nPort);
	CString str;
	str.Format("%d-%d对所有人说:\r\n%s\r\n",szIP,nPort,s);

	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());
		list.GetNext(pos);
	}

	CSocket::OnReceive(nErrorCode);
}


9、 在CClientSocket类中添加 虚函数OnClose,用于监测客户端是否断开了连接。

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);
}
10、主对话框类CServerDlg的头文件中,添加CListenSocket类型的成员变量m_sock。
#include "ListenSocket.h"

class CServerDlg : public CDialog
{
	CListenSocket m_sock;//添加CListenScoket类型的成员变量
……
11、修改主对话框 CServerDlg中的初始化函数,创建Socket并开始侦听。

BOOL CServerDlg::OnInitDialog()//初始化函数代码,创建socket并开始侦听
{
	CDialog::OnInitDialog();

	if(m_sock.Create(8118))
		m_sock.Listen();
	else
	{
		CString str;
		str.Format("Socket Create Error.%d",GetLastError());
		AfxMessageBox(str);
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

12、编译运行即可,接下来创建客户端程序。


第二步:创建Client服务器程序。

1、创建Client工程,记得第二部勾选勾选Window Sockets

2、主对话框中添加控件,如下图所示。

3、修改控件的属性列表。
控件类型		ID				CaptionStyle
Edit			IDC_HIST		多行、垂直滚动条、只读(去掉自动水平滚动条)
Edit			IDC_INPUT
Button			IDOK			发送(&S)
Button		 	IDCANCEL			关闭
4、创建CSocket的派生类CConnectSocket,过程同 第一步:创建Server服务器程序——第4步相同。
5、在CConnectSocket类中添加虚函数OnReceive,用于截获服务器发来的网络数据。
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)-1);
	if(nLen<=0)
		return ;
	s[nLen]=0;
	CWnd* pWnd = AfxGetMainWnd();
	CEdit* pEdit = (CEdit*)pWnd->GetDlgItem(IDC_HIST);
	pEdit->SetSel(pEdit->GetWindowTextLength(),-1);
	pEdit->ReplaceSel(s);

	CSocket::OnReceive(nErrorCode);
}<span style="color:#3333ff;">
</span>
6、主对话框类头文件中添加一个CConnectSocket类型的成员变量。
#include "onnectSocket.h"//由于少写了个C
class CClientDlg : public CDialog
{
	CConnectSocket m_sock;
7、修改主对话框中的初始化函数代码。
// CClientDlg message handlers

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

	m_sock.Create();
	if (!m_sock.Connect("192.168.1.46",8118))<span style="white-space:pre">	</span>//此处的IP地址记得写成自己电脑的IP
	{
		//连接服务器端运行的主机IP地址
		CString str;
		str.Format("连接失败:%d",GetLastError());
		AfxMessageBox(str);
	}
……
8、主对话框的类中,添加“发送(&S)”按钮的消息 映射函数OnOK。
void CClientDlg::OnOK() 
{
	// TODO: Add extra validation here
	CString szText;
	GetDlgItemText(IDC_INPUT,szText);
	if(m_sock.Send(szText,szText.GetLength())>0)
	{
		CEdit *pEdit = (CEdit*)GetDlgItem(IDC_HIST);
		pEdit->SetSel(pEdit->GetWindowTextLength(),-1);
		pEdit->ReplaceSel("\n你对所有人说:\r\n"+szText+"\r\n");
	}
	//CDialog::OnOK();
}

9、编译运行,首先要开启编译好的服务器端程序,再在一台或多台计算机开启客户端程序经行调试。
运行结果如下:






评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值