基于CSocket网络聊天室程序

基于CSocket网络聊天室程序

项目介绍

  1. 通过CSocket类提供的功能来实现多人聊天
  2. 从CSocket派生出两个类:ClistenSocket和CclientSocket,它们分别用来侦听客户的连接请求和建立与客户的连接
  3. 服务器只需要——个侦听套接字ClistenSocket,然后根据客户的连接请求动态创建客户套接字CclientSocket
  4. 基于TCP网络,客户端与服务器完成信息交互

服务器端代码实现

首先新建对话框工程
聊天室服务器
添加IP控件变量m_ip,编辑控件变量m_nServPort,修改按钮为启动服务器。新建一个类CSeverScoket,基类为CSocket,进入重写页面在重写虚函数OnAccept代码如下:

void CServerSocket::OnAccept(int nErrorCode)
{
	// TODO: 在此添加专用代码和/或调用基类
	CClientSocket*psocket = new CClientSocket();
	if(Accept(*psocket))
		m_socketlist.AddTail(psocket);
	else
		delete psocket;

	CSocket::OnAccept(nErrorCode);
}

代码中CClientSocket类也是基类为CSocket的新增类;
继续为类CSeverScoket增加成员函数SendAll,用于给各个客户端发消息。代码如下:

void CServerSocket::SendALL(char *bufferdata, int len)
{
	if(len != -1)
	{
	 bufferdata[len]=0;
	 POSITION pos = m_socketlist.GetHeadPosition(); 
	 while(pos !=NULL)
	   {
	    CClientSocket*socket = (CClientSocket*)m_socketlist.GetNext(pos);
	    if(socket != NULL)
	      socket->Send(bufferdata,len);
	   }
	}
}

m_socketlist是CServerSocket的成员函数CPtrList m_socketlist;
继续为类CSeverScoket增加成员函数DelAll,代码如下:`

void CServerSocket::DelAll()
{
   POSITION pos = m_socketlist.GetHeadPosition(); 
   while(pos !=NULL)
	   {
	    CClientSocket*socket = (CClientSocket*)m_socketlist.GetNext(pos);
	    if(socket != NULL)
	      delete socket;
	   }
	m_socketlist.RemoveAll(); 
}

接下来为CClientSocket类添加代码,用于和客户端信息交互,首先接收信息重写虚函数OnReceive,代码如下:

void CClientSocket::OnReceive(int nErrorCode)
{
	// TODO: 在此添加专用代码和/或调用基类
	char bufferdata [2048];
	int len =Receive (bufferdata,2048);
	bufferdata[len] = '\0';
	theApp.m_ServerSock.SendALL (bufferdata,len);
	CSocket::OnReceive(nErrorCode);
}

socket对象的作用域在App类中,在App类中加入socket库的初始化

BOOL CServerApp::InitInstance()
{
    WSADATA wsd;
	AfxSocketInit(&wsd);

最后给启动服务器添加消息处理函数

void CServerDlg::OnBnClickedOk()
{
	// TODO: 在此添加控件通知处理程序代码
	  UpdateData ();
     CString strIP;
	 BYTE nf1,nf2,nf3,nf4;
	 m_IP.GetAddress(nf1,nf2,nf3,nf4); 
	 strIP.Format(_T("%d.%d.%d.%d"),nf1,nf2,nf3,nf4);
	 if(m_nServPort>1024 && !strIP.IsEmpty ())
	 {
	   theApp.m_ServerSock.Create(m_nServPort,SOCK_STREAM,strIP);
	   BOOL ret = theApp.m_ServerSock.Listen ();               //开始监听
	   if (ret)
	     AfxMessageBox(_T("启动成功"));
	 }
	 else 
		 AfxMessageBox(_T("信息设置错误"));
	 CDialogEx::OnOK();

}

再添加摧毁事件处理函数

void CServerDlg::OnDestroy()
{
	 CDialogEx::OnDestroy();
	 theApp.m_ServerSock.DelAll(); 
}

这样服务端就完成了,输入正确的IP地址和端口号就可以使用了端口号要大于1024!
在这里插入图片描述

客户器端代码实现

新建两个对话框登录服务器对话框和聊天对话框:
在这里插入图片描述
在这里插入图片描述
同样先进行套接字库初始化与上文一样;登录对话框首先连接服务器,登录代码如下:

void CclientDlg::OnBnClickedOk()  //denglu
{
	// TODO: 在此添加控件通知处理程序代码
	CString strIP,strPort;
	UINT port;

	UpdateData ();
	if(m_IP.IsBlank () ||m_nServPort <1024||m_strNickname.IsEmpty())
	{
		AfxMessageBox (_T("请设置服务器信息"));
		return;
	}
	BYTE nf1,nf2,nf3,nf4;
	m_IP.GetAddress (nf1,nf2,nf3,nf4);
	strIP.Format(_T("%d.%d.%d.%d"),nf1,nf2,nf3,nf4);
	theApp.m_strName = m_strNickname;
	if (theApp.m_clientsock.Connect (strIP ,m_nServPort ))
	{
		AfxMessageBox (_T("连接服务器成功"));
		ChatDlg dlg;
		theApp.m_clientsock.SetWnd(&dlg);
		dlg.DoModal();
	}
	else
	{
		AfxMessageBox (_T("连接服务器失败"));
	}

}
// CClientSocket 成员函数 消息传递
void CClientSocket ::SetWnd( ChatDlg *pDlg)
{
	m_pDlg = pDlg;
}

ClientSocket m_clientsock为Client的成员变量
同样添加类ClientSocket,重载虚函数OnReceive,用于接收服务器端发来的消息,代码如下:

oid CClientSocket::OnReceive(int nErrorCode)
{
	// TODO: 在此添加专用代码和/或调用基类

	if (m_pDlg)
	{
		char buffer[2048];
		CString str;
		int len=Receive(buffer,2048);
		if(len != -1)
		{
			buffer[len] ='\0';
			buffer[len+1]='\0';
			str.Format (_T("%s"),buffer);			
			m_pDlg->m_list.InsertString(i,str);
			m_pDlg-> GetDlgItem(IDC_EDIT1)->SetWindowText(_T(""));
		}
	}
	i++;
	CSocket::OnReceive(nErrorCode);
}

切换资源视图在聊天对话框中添加发送按钮的消息处理函数

void CclientDlg::OnBnClickedOk()  //denglu
{
	// TODO: 在此添加控件通知处理程序代码
	CString strIP,strPort;
	UINT port;

	UpdateData ();
	if(m_IP.IsBlank () ||m_nServPort <1024||m_strNickname.IsEmpty())
	{
		AfxMessageBox (_T("请设置服务器信息"));
		return;
	}
	BYTE nf1,nf2,nf3,nf4;
	m_IP.GetAddress (nf1,nf2,nf3,nf4);
	strIP.Format(_T("%d.%d.%d.%d"),nf1,nf2,nf3,nf4);
	theApp.m_strName = m_strNickname;
	if (theApp.m_clientsock.Connect (strIP ,m_nServPort ))
	{
		AfxMessageBox (_T("连接服务器成功"));
		ChatDlg dlg;
		theApp.m_clientsock.SetWnd(&dlg);
		dlg.DoModal();
	}
	else
	{
		AfxMessageBox (_T("连接服务器失败"));
	}

}

最后我们运行一下就可以了
在这里插入图片描述
源码下载
https://download.csdn.net/download/weixin_51071767/21979551?spm=1001.2014.3001.5503

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

涛声依旧1992

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值