[MFC]服务端客户端一对一聊天

客户端部分:

Dlg.cpp:

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

/*

Process:

1.创建工程,允许windows库;
2.画界面,设定变量;
3.SetDlgItemText初始化IP,初始化端口值
4.CSocket类派生出 Mysocket,并重载receive send connect函数;大主类增加id的CString和一个MySocket变量
5.互相添加头文件
6.receive重载:	1)对话框指针
				2)字符串,字符串长度,ircvd的一个int变量
				3)※※※ircvd=receive(串,长)接收数据,socket_error排错
				4)pbuf[ircvd]=NULL;;;通过 对话框指针 往 接收框 里 += 信息
				5)更新窗口
7.connect重载: 1)对话框指针
				2)获得参数code值,CString字符串用作马甲(其实可以没有)
				3)※※※连上的话参数code值应该为0 排错
				4)“连接成功!”,改变按钮,更新窗口
8.按钮 连接:	1)※※※AfxSocketInit 连接,成功==1,排错
				2)※通过GetDlgItemText 取得ip的CString
				3)初始化m_socket.m_hSocket = INVALID_SOCKET  为空
				4)※※※Mysocket  .creat一个,并判断socket_error排错
				5)※※※.connect(IP字符串,PORT端口值)连接
9.按钮 发送:	1)※※※.Send(LPCTSTR(CS串),CS串.getlength) 发送数据,SOCKET_ERROR排错
				2)显示在自己的屏幕上并更新

Error Reporder:

1.SetDlgItemText设置ipADRESS
参数要求(IPadress的ID, _T("127.0.0.1")); 后面的_T("")很重要!

2.如果出现  CID_DIALOG1 未定义
那么在出错位置上  加一行 #include “resource.h”

3.m_socket.Send(*char, ilen);	//将信息  send出去,要把CString转化成char *,如下:

#include <atlbase.h>	//char  CString
USES_CONVERSION;
char *m_mesc = T2A(m_mes);		//转化  char cstring

4.LPCTSTR不能用_T 因为_T只能将“”编程TCHAR类型,不能修改变量;而LPCTSTR可以!

5.socket等物质头文件关系要处理好,“未声明的标识符”就是这个错误!

*/

#include "stdafx.h"
#include "MFC_Chat.h"
#include "MFC_ChatDlg.h"
#include "afxdialogex.h"
#include <atlbase.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

///自动生成部分省略///

void CMFC_ChatDlg::OnBnClickedConnect()
{
	// TODO:  在此添加控件通知处理程序代码
	if (!AfxSocketInit())			//连接成功否?
	{
		AfxMessageBox(_T("IDP_SOCKETS_INIT_FAILED"));	//翻译:连接失败
		return;
	}
	GetDlgItemText(IDC_IPADDRESS1, m_ipstr);		//dword类型的IP地址转化为字符串ipstr
	m_socket.m_hSocket = INVALID_SOCKET;			//并不理解
	UpdateData(true);
	BOOL flag = m_socket.Create();					//创建插座/嵌套字
	if (!flag)
	{
		AfxMessageBox(_T("SOCKET ERROR"));
		return;
	}
	m_socket.Connect(m_ipstr, m_port);				//给出IP和端口进行连接

}


void CMFC_ChatDlg::OnBnClickedSend()
{
	// TODO:  在此添加控件通知处理程序代码
	int ilen;
	int isent;
	UpdateData(true);
	if (m_mes != "")
	{
		ilen = m_mes.GetLength();

		USES_CONVERSION;
		char *m_mesc = T2A(m_mes);		//转化  char cstring

		isent = m_socket.Send(m_mesc, ilen);	//将信息转化成LPCTSTR类型  send出去
		if (isent == SOCKET_ERROR)
		{
			MessageBox(_T("连接失败,请重试!"));
		}
		else
		{
			m_recmes += "客户机:";
			m_recmes += m_mes;
			m_recmes += "\r\n";
			UpdateData(false);
		}
	}
}


MySocket.cpp:

void MySocket::OnReceive(int nErrorCode)
{
	// TODO:  在此添加专用代码和/或调用基类
	//获取对话框指针
	CMFC_ChatDlg *pDlg = (CMFC_ChatDlg*)AfxGetMainWnd();		//获取对话框指针!!!!
	//往编辑框插入消息
	char *pbuf = new char[4096];
	int ibufsize = 4096;
	int ircvd;
	//CString strrecvd;	//Unknown
	//接收数据
	memset(pbuf, 0, sizeof(pbuf));
	ircvd = Receive(pbuf, ibufsize);			//得到初始位置? 参数:字符串 + 长度
	if (ircvd == SOCKET_ERROR)
	{
		pDlg->MessageBox(_T("SOCKET_ERROR"));	//报错
	}
	else
	{
		pbuf[ircvd] = '\0';						//用作结尾\0
		pDlg->m_recmes += "服务器:";
		pDlg->m_recmes += pbuf;
		pDlg->m_recmes += "\r\n";
		pDlg->UpdateData(false);				//更新hy
	}
	delete[] pbuf; 

	CAsyncSocket::OnReceive(nErrorCode);
}

void MySocket::OnConnect(int nErrorCode)
{
	// TODO:  在此添加专用代码和/或调用基类
	CMFC_ChatDlg * pDlg = (CMFC_ChatDlg*)AfxGetMainWnd();
	int iResult = nErrorCode;
	CString buffer;
	//int namelen;			//不知何为

	if (iResult != 0)			//连接失败
	{
		buffer.Format(_T("服务器连接失败。\r\n"));
		pDlg->m_recmes += buffer;
	}
	else
	{
		//namelen = sizeof(sockaddr_in);		//不知何为
		buffer.Format(_T("成功连接到服务器"));
		pDlg->m_recmes = buffer;
		pDlg->m_recmes += pDlg->m_ipstr;
		buffer.Format(_T(":%u \r\n", pDlg->m_port));
		pDlg->m_recmes += buffer;
		pDlg->GetDlgItem(IDC_SEND)->EnableWindow(true);		//控制按钮
	}
	pDlg->UpdateData(false);

	

	CAsyncSocket::OnConnect(nErrorCode);
}


服务端部分:

Dlg.cpp:

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

/*

Process:

1.创建工程,允许windows库;
2.画界面,设定变量;
3.SetDlgItemText初始化端口值
4.CSocket类派生出 Mysocket,并重载receive 函数;继续派生MySerSocket,重载accepted函数;大主类增加一个MySerSocket变量,MySerSocket增加MySocket变量
5.互相添加头文件
6.receive重载:	1)对话框指针
				2)字符串,字符串长度,ircvd的一个int变量
				3)爱咋咋地!
7.accepted重载:1)new一个MySocket嵌套字
				2)Accept(新嵌套字)
				3)执行嵌套字里的AsyncSelect(FD_READ)函数;
8.按钮 开服:	1)AfxSocketInit() 初始化嵌套字
				2)m_sersocket.Create(m_port) 根据端口开放
				3)m_sersocket.Listen(1) 开始监听
9.其他的发送什么的自便。

*/


#include "stdafx.h"
#include "MFC_ChatSer.h"
#include "MFC_ChatSerDlg.h"
#include "afxdialogex.h"

#include <atlbase.h>	//char  CString
//照例省略
void CMFC_ChatSerDlg::OnBnClickedListen()
{
	// TODO:  在此添加控件通知处理程序代码
	UpdateData(true);
	if (!AfxSocketInit())
	{
		AfxMessageBox(_T("IDP_SOCKET_INIT_FAILED"));
		return;
	}
	BOOL flag = m_sersocket.Create(m_port);
	if (!flag)
	{
		AfxMessageBox(_T("SOCKET_ERROR"));
		return;
	}
	flag = m_sersocket.Listen(1);			//开始监听
	if (!flag)
	{
		AfxMessageBox(_T("SOCKET_ERROR"));
		return;
	}
	SetDlgItemText(IDC_LISTEN, _T("正在监听"));
	CMFC_ChatSerDlg *pDlg = (CMFC_ChatSerDlg*)AfxGetMainWnd();
	pDlg->GetDlgItem(IDC_LISTEN)->EnableWindow(false);
}


void CMFC_ChatSerDlg::OnBnClickedSend()
{
	// TODO:  在此添加控件通知处理程序代码
	int ilen;
	int isent;
	UpdateData(true);
	if (m_mes != "")
	{
		ilen = m_mes.GetLength();

		USES_CONVERSION;
		char *m_mesc = T2A(m_mes);		//转化  char cstring

		isent = m_sersocket.m_socket->Send(m_mesc, ilen);
		if (isent == SOCKET_ERROR)
		{
			MessageBox(_T("连接失败,请重试!"));
		}
		else
		{
			m_recmes += "服务器:";
			m_recmes += m_mes;
			m_recmes += "\r\n";
			UpdateData(false);
		}
	}
}
MySerSocket核心部分:
void CMySerSocket::OnAccept(int nErrorCode)
{
	// TODO:  在此添加专用代码和/或调用基类

	CMFC_ChatSerDlg *pDlg = (CMFC_ChatSerDlg*)AfxGetMainWnd();
	//显示连接消息
	pDlg->m_recmes += "客户端连入服务器";
	pDlg->m_recmes += "\r\n";
	pDlg->UpdateData(false);
	pDlg->GetDlgItem(IDC_SEND)->EnableWindow(true);

	MySocket * psocket = new MySocket();
	if (Accept(*psocket))
	{
		psocket->AsyncSelect(FD_READ);		//开启读取监听???
		m_socket = psocket;
	}
	else 
		delete psocket;

	CAsyncSocket::OnAccept(nErrorCode);
}

MySocket核心部分:

void MySocket::OnReceive(int nErrorCode)
{
	// TODO:  在此添加专用代码和/或调用基类
	//获取对话框指针
	CMFC_ChatSerDlg *pDlg = (CMFC_ChatSerDlg*)AfxGetMainWnd();		//获取对话框指针!!!!
	//往编辑框插入消息
	char *pbuf = new char[4096];
	int ibufsize = 4096;
	int ircvd;
	//CString strrecvd;	//Unknown
	//接收数据
	ircvd = Receive(pbuf, ibufsize);			//得到初始位置? 参数:字符串 + 长度
	if (ircvd == SOCKET_ERROR)
	{
		pDlg->MessageBox(_T("SOCKET_ERROR"));	//报错
	}
	else
	{
		pbuf[ircvd] = NULL;
		pDlg->m_recmes += "客户端:";
		pDlg->m_recmes += pbuf;
		pDlg->m_recmes += "\r\n";
		pDlg->UpdateData(false);				//更新hy
	}
	delete[] pbuf;

	CAsyncSocket::OnReceive(nErrorCode);
	CAsyncSocket::OnReceive(nErrorCode);
}


环境:Windows XP SP3、 VC++ 6.0、 Windows 2003 SDK 使用步骤: 1、下载解压之后,使用VC++ 6.0打开两个工程:一个是SocketServer和一个ClientSocket工程。 2、首先运行服务器端工程,选默认的端口1008 3、然后运行客户端工程,选默认的端口1008和默认的服务器地址 4、再运行多个客户端进程 5、如果一切正常,可以每个客户端的消息发送,我们可以在服务端和各个客户端同步看到消息 实现一个服务器对多个客户端的关键是,在服务端的使用集合CPtrList类用保存客户端的socket对象,思想与Java中的编程思想一样,只不过Java中会使用多线程技术,在Vector集合保存客户端的socket对象,而MFC框架提供了CSocket类,它是一个异步通信的类,所以看上去代码比较Java的多线程代码简单的实现了一个对多的即时通讯功能。另外,MFC提供了CSocketFile类和CArchive类与CSocket类实现了C++的网络通讯编程功能。 本示例注释非常详细,所有的辅助类都放一个util目录中,然后在工程中分了一个目录来管理这些辅助类,使用代码非常清晰。手动书写部分的代码是按Java的规范书写,当然其它代码由IDE生成的,所以是MS的风格,所以当你看代码时,只要是使用“骆驮命名法”的方法都是本人书写的功能性代码。 参看的思路:在服务端要从回调方法onAccept读起;而客户端代码主要从OnSendButton方法读起,即可理解整个代码的意思。 阅读对象:具有Java的Socket编程经验的人员,并且希望能够书写出比Java效率更高的即时通讯程序的人员
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值