C++/MFC-套接字CSocket之一般流程

一、用CSocket 建立服务端程序步骤

//API版

// 服务器端程序:
// 1、加载套接字库WSAStartup 环境初始化
// 2、创建套接字(socket)。
// 3、将套接字绑定到一个本地地址和端口上(bind)。
// 4、将套接字设为监听模式,准备接收客户请求(listen)。
// 5、等待客户请求到来;当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept)。
// 6、用返回的套接字和客户端进行通信(send/recv)。
// 7、返回,等待另一客户请求。
// 8、关闭套接字。
// 9、清理套接字环境,释放资源WSACleanup

MFC版:

1、 套接字环境初始化 AfxSocketInit

2、创建套接字对象Create

3、 绑定IP地址及端口Create 

4、 监听 Listen

5、 等待请求到来: 重写OnAccept虚函数,接收相应消息,(然后调用Accept成员函数返回 客户端套接对象)

6、 消息分发处理 :重写OnReceive虚函数,接收相应消息,(然后调用Receive成员函数返回消息);发送时,直接调用成员函数Send

客户端:

1、 套接字环境初始化 AfxSocketInit
2、创建套接字对象Create
3、 绑定IP地址及端口Create 
4、 监听 Listen
5、 消息分发处理 :重写OnReceive虚函数,接收相应消息,(然后调用Receive成员函数返回消息);发送时,直接调用成员函数Send

二、服务器端示例

新建工程CSocket_Server


在***App::InitInstance      

//1、 套接字环境初始化 AfxSocketInit

 WSADATA  data;
if (AfxSocketInit(&data))//AfxSocketInit返回值非零表示成功
{
       TRACE("AfxSocketInit 初始化成功\n");
}


派生自己的套接字类

class CMySocket : public CSocket
并重写
virtual void OnClose(int nErrorCode);
virtual void OnReceive(int nErrorCode);
virtual void OnAccept( int nErrorCode );

class CCSocket_ServerDlg;
class CMySocket : public CSocket
{
public:
	CMySocket();
	virtual ~CMySocket();
	virtual void OnClose(int nErrorCode);
	virtual void OnReceive(int nErrorCode);
	virtual void OnAccept(int nErrorCode);
	void setDlg(CCSocket_ServerDlg * Dlg);

private:
	CCSocket_ServerDlg * m_pDlg;
};
.cpp

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

#include "stdafx.h"
#include "CSocket_Server.h"
#include "MySocket.h"
#include "CSocket_ServerDlg.h"


// CMySocket

CMySocket::CMySocket()
{
}

CMySocket::~CMySocket()
{
}


// CMySocket 成员函数
void CMySocket::OnClose(int nErrorCode)
{
	if (nErrorCode == 0)
	{
		m_pDlg->OnClose();
	}
	return;

}

void CMySocket::OnReceive(int nErrorCode)
{
	if (nErrorCode == 0) 
		m_pDlg->OnReceive();
	return;

}

void CMySocket::OnAccept(int nErrorCode)
{
	if (nErrorCode == 0) 
		m_pDlg->OnAccept();
	return;

}

void CMySocket::setDlg(CCSocket_ServerDlg * Dlg)
{
	m_pDlg = Dlg;
}

注:为什么要使用m_pDlg->OnClose();。。。等函数?

是为了将他们能够在一个.cpp文件中编写。

PS:我们自己新建的CMySocket类是连接CSocket类和主窗口类(CCSocket_ServerDlg)的。


在主类CCSocket_ServerDlg中     

//2、创建套接字对象Create    3、 绑定IP地址及端口Create    4、 监听 Listen

UpdateData(true);//从窗口获取数据
BOOL flag = m_ServerSocket.Create(m_nPort);//创建套接字,绑定端口,IP
if (flag)
{
	TRACE("create and bind successful");
	if (m_ServerSocket.Listen())
	{
		TRACE("listen  successful");
	}
}

在CCSocket_ServerDlg.h文件中,   

 //5、 等待请求到来  OnAccept 、Accept 6、 消息分发处理  OnReceive、Receive

添加

CMySocket m_ServerSocket;//服务器套接字
CMySocket m_ClientSocket;//新连接的客户端套接字

void OnClose(void);
void OnReceive(void);
void OnAccept(void);

void CCSocket_ServerDlg::OnClose(void)
{
	m_ServerSocket.Close();
	m_ClientSocket.Close();
}

void CCSocket_ServerDlg::OnReceive(void)
{
	char* pBuf[1025] = { 0 };
	int nBuffSize = 1024;
	int r = m_ClientSocket.Receive(pBuf, nBuffSize);
	if (r != SOCKET_ERROR)
	{
		//具体代码
		UpdateData(false);
	}
	else
	{
		AfxMessageBox(_T("数据接收错误!"), MB_OK | MB_ICONSTOP);
		return;
	}
}

void CCSocket_ServerDlg::OnAccept(void)
{
	m_ServerSocket.Accept(m_ClientSocket); //获取新连接对象即可
}

注意:此处调用的是CSocket的Accept、Receive、Close函数。

在.cpp中

// TODO: 在此添加额外的初始化代码
m_ServerSocket.setDlg(this);
m_ClientSocket.setDlg(this);

发送     

//6、 消息分发处理    Send

UpdateData(true);
if (!m_strMsg.IsEmpty())  //判断msg编辑框是否为空
{
	m_ClientSocket.Send(LPCTSTR(m_strMsg.GetString()), 2 * m_strMsg.GetLength());  //发送消息
	m_listSend.AddString(m_strMsg);  //添加到列表中
	m_strMsg.Empty();  //清空编辑框
	UpdateData(false);
}

三、客户端示例

右键->新建项目。

新建一个CSocket_Client的项目。

注意:客户端不需要重写OnAccept

②③⑤⑥同上

④在主类中

//2、创建套接字对象Create    3、 绑定IP地址及端口Create    4、 监听 Listen

UpdateData(true);
if (m_ClientSocket.Create())
{
	if (m_ClientSocket.Connect(m_strIP, m_nPORT))
	{
		TRACE("link server successful");
	}
}

右键->设置启动项目,

将其更改为一下:

C++/MFC-套接字CSocket之一般流程_第1张图片

注:可有.send获得发送的字节数

int sendlen=myClientSocket.Send(m_strMsg,m_strMsg.GetLength()*2);
TRACE("成功发送%d 字节\n",sendlen);


四、最后的结果:

此时,服务器和客户端可相互通信。

C++/MFC-套接字CSocket之一般流程_第2张图片

代码:CSocket_Server.zip

五、注意事项

①客户端不需要重写OnAccept

②客户端的链接(即create、connect)和服务器的链接(create、listen)不一样

③注意重写窗口销毁函数,调用 OnClose();函数

④为了防止误操作,注意按钮的禁用(button.EnableWindow(false);)和使用(button.EnableWindow(true);)


你可能感兴趣的:(C++/MFC-套接字)