通信网原理实验报告编程实现聊天程序.docx
- 文档编号:6645198
- 上传时间:2023-01-08
- 格式:DOCX
- 页数:27
- 大小:188.29KB
通信网原理实验报告编程实现聊天程序.docx
《通信网原理实验报告编程实现聊天程序.docx》由会员分享,可在线阅读,更多相关《通信网原理实验报告编程实现聊天程序.docx(27页珍藏版)》请在冰豆网上搜索。
通信网原理实验报告编程实现聊天程序
实验三编程实现聊天程序
一、实验目的
1.熟悉VisualC++的基本操作;
2.基本了解基于对话框的windows应用程序的编写过程;
3.对于WindowsSocket编程建立初步概念。
二、实验环境
1.PC机一台;
2.VisualC++软件。
三、实验内容
(一)客户端
客户端聊天程序需要完成以下几个功能:
(1)客户端聊天程序要负责建立和维护与服务器的连接,通过获取用户的设置尝试与服务器的连接,并且随时检测连接的状态。
(2)客户端聊天程序要把用户输入的信息及时发送到聊天服务器。
一般情况下,当用户输入一行信息并且按下回车键后聊天程序就要把这一行信息发送出去,才能及时地满足用户的交互需求。
(3)要随时准备好接受来自服务器的信息,随时把接受到的信息显示出来,让用户及时看到对方的响应。
(4)在用户退出聊天过程是要关闭与服务器的连接。
比较好的做法是提前通知服务器或者直接给服务器发送一条退出通知,使得服务器能够及时掌握客户端的连接状态,把对方客户的退出信息及时发送到对等实体上。
客户端聊天程序如下:
//ClientDlg.cpp:
implementationfile
//
#include"stdafx.h"
#include"Client.h"
#include"ClientDlg.h"
#ifdef_DEBUG
#definenewDEBUG_NEW
#undefTHIS_FILE
staticcharTHIS_FILE[]=__FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
//CAboutDlgdialogusedforAppAbout
classCAboutDlg:
publicCDialog
{
public:
CAboutDlg();
enum{IDD=IDD_ABOUTBOX};
protected:
virtualvoidDoDataExchange(CDataExchange*pDX);//DDX/DDVsupport
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg:
:
CAboutDlg():
CDialog(CAboutDlg:
:
IDD)
{
}
voidCAboutDlg:
:
DoDataExchange(CDataExchange*pDX)
{
CDialog:
:
DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg,CDialog)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//CClientDlgdialog
CClientDlg:
:
CClientDlg(CWnd*pParent/*=NULL*/)
:
CDialog(CClientDlg:
:
IDD,pParent)
{
m_strDisplay=_T("");
m_strSend=_T("");
m_bWhispering=FALSE;
m_hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
voidCClientDlg:
:
DoDataExchange(CDataExchange*pDX)
{
CDialog:
:
DoDataExchange(pDX);
DDX_Control(pDX,IDC_LIST_USER,m_lbUser);
DDX_Text(pDX,IDC_EDIT_DIAPLAY,m_strDisplay);
DDX_Text(pDX,IDC_EDIT_SEND,m_strSend);
DDX_Check(pDX,IDC_CHECK_WHISPERING,m_bWhispering);
}
BEGIN_MESSAGE_MAP(CClientDlg,CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BN_CONNECT,OnBnConnect)
ON_BN_CLICKED(IDC_BN_CLOSE,OnBnClose)
ON_BN_CLICKED(IDC_BN_SEND,OnBnSend)
ON_MESSAGE(WM_RECEIVE,OnReceive)
ON_MESSAGE(WM_SOCKETCLOSE,OnServerClose)
ON_MESSAGE(WM_SEND,OnSend)
ON_MESSAGE(WM_CONNCET,OnConnect)
ON_LBN_DBLCLK(IDC_LIST_USER,OnDblclkListUser)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//CClientDlgmessagehandlers
BOOLCClientDlg:
:
OnInitDialog()
{
CDialog:
:
OnInitDialog();
ASSERT((IDM_ABOUTBOX&0xFFF0)==IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX<0xF000);
CMenu*pSysMenu=GetSystemMenu(FALSE);
if(pSysMenu!
=NULL)
{
CStringstrAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if(!
strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu);
}
}
SetIcon(m_hIcon,TRUE);//Setbigicon
SetIcon(m_hIcon,FALSE);//Setsmallicon
//参数初始化
m_Socket.Initialize(this);
m_strNetIP=_T("127.0.0.1");
m_iNetPort=3127;
m_bConnect=FALSE;
GetDlgItem(IDC_BN_CLOSE)->EnableWindow(FALSE);
GetDlgItem(IDC_BN_SEND)->EnableWindow(FALSE);
returnTRUE;//returnTRUEunlessyousetthefocustoacontrol
}
voidCClientDlg:
:
OnSysCommand(UINTnID,LPARAMlParam)
{
if((nID&0xFFF0)==IDM_ABOUTBOX)
{
CAboutDlgdlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog:
:
OnSysCommand(nID,lParam);
}
}
voidCClientDlg:
:
OnPaint()
{
if(IsIconic())
{
CPaintDCdc(this);//devicecontextforpainting
SendMessage(WM_ICONERASEBKGND,(WPARAM)dc.GetSafeHdc(),0);
intcxIcon=GetSystemMetrics(SM_CXICON);
intcyIcon=GetSystemMetrics(SM_CYICON);
CRectrect;
GetClientRect(&rect);
intx=(rect.Width()-cxIcon+1)/2;
inty=(rect.Height()-cyIcon+1)/2;
dc.DrawIcon(x,y,m_hIcon);
}
else
{
CDialog:
:
OnPaint();
}
}
HCURSORCClientDlg:
:
OnQueryDragIcon()
{
return(HCURSOR)m_hIcon;
}
voidCClientDlg:
:
OnBnConnect()
{
CStringstrConnectError;
//获取用户名字
CInputDlginputDlg;
intiResult=inputDlg.DoModal();
if(iResult==IDCANCEL){return;}
m_strName=inputDlg.m_strName;
//创建套接字
if(!
m_Socket.Create())
{
strConnectError.LoadString(IDS_FAIL_CREATE_SOCKET);
ShowInDisplay(strConnectError);
return;
}
CStringstrInfo;
strInfo.LoadString(IDS_CONNECTING);
ShowInDisplay(strInfo);
//连接服务器
if(!
m_Socket.Connect(m_strNetIP,m_iNetPort))
{
intn=m_Socket.GetLastError();
strConnectError.LoadString(IDS_FAIL_CONNECT);
ShowInDisplay(strConnectError);
return;
}
strInfo.LoadString(IDS_SUCCEED_CONNECT);
ShowInDisplay(strInfo);
m_bConnect=TRUE;
//发送自已的名字
NETMESSAGEnetMessage(PTC_NEW,m_strName,_T(""),_T(""));
m_Socket.SendMsg(netMessage);
GetDlgItem(IDC_BN_CONNECT)->EnableWindow(FALSE);
GetDlgItem(IDC_BN_CLOSE)->EnableWindow(TRUE);
GetDlgItem(IDC_BN_SEND)->EnableWindow(TRUE);
}
voidCClientDlg:
:
OnBnClose()
{
if(m_bConnect)
{
m_Socket.Close();
m_bConnect=FALSE;
GetDlgItem(IDC_BN_CONNECT)->EnableWindow(TRUE);
GetDlgItem(IDC_BN_CLOSE)->EnableWindow(FALSE);
GetDlgItem(IDC_BN_SEND)->EnableWindow(FALSE);
m_lbUser.ResetContent();
CStringstrMsg;
strMsg.LoadString(IDS_BREAK);
ShowInDisplay(strMsg);
}
}
voidCClientDlg:
:
OnBnSend()
{
OnSend();
m_strSend=_T("");
UpdateData(FALSE);
}
voidCClientDlg:
:
OnReceive()
{
NETMESSAGEnetMessage;
m_Socket.Receive((char*)&netMessage,sizeof(netMessage));
CStringstrForm=netMessage.form;
//过滤自已发出的信息
if(strForm==m_strName)return;
CStringstrTo=netMessage.to;
CStringstrMsg=netMessage.data;
switch(netMessage.type)
{
casePTC_USER_LIST:
//用户列表
m_lbUser.AddString(strMsg);
break;
casePTC_NEW:
//新用户进入
m_lbUser.AddString(strForm);
ShowInDisplay(strMsg);
break;
casePTC_SAY:
ShowMessage(netMessage);
casePTC_WHISPERING:
//密语
if(strTo!
=m_strName)return;
ShowMessage(netMessage);
break;
casePTC_CLIENT_QUIT:
//有用户退出
m_lbUser.DeleteString(m_lbUser.FindString(-1,strForm));
ShowInDisplay(strMsg);
break;
}
}
voidCClientDlg:
:
OnServerClose()
{
if(!
m_bConnect)return;
CStringstrMsg;
strMsg.LoadString(IDS_SERVER_CLOSE);
ShowInDisplay(strMsg);
m_Socket.Close();
m_bConnect=FALSE;
GetDlgItem(IDC_BN_CONNECT)->EnableWindow(TRUE);
GetDlgItem(IDC_BN_CLOSE)->EnableWindow(FALSE);
GetDlgItem(IDC_BN_SEND)->EnableWindow(FALSE);
m_lbUser.ResetContent();
}
voidCClientDlg:
:
OnSend()
{
UpdateData(TRUE);
//主要是填充NETMESSAGE结构体
NETMESSAGEnetMessage;
strcpy(netMessage.form,m_strName);
strcpy(netMessage.data,m_strSend);
//取得列表框中的用户
if(m_lbUser.GetText(m_lbUser.GetCurSel(),netMessage.to)==LB_ERR)
{
strcpy(netMessage.to,_T(""));
}
if(m_bWhispering)
{
//密语
CStringstrTo=netMessage.to;
if(strTo==_T(""))
{
MessageBox("请选择对方!
","错误");
return;
}
netMessage.type=PTC_WHISPERING;
}
else
{
strcpy(netMessage.to,_T("所有人"));
netMessage.type=PTC_SAY;
}
//发送该信息
m_Socket.SendMsg(netMessage);
//显示发送信息
CStringstrTo=netMessage.to;
CStringstrMsg=netMessage.data;
ShowInDisplay("你对"+strTo+"说:
"+strMsg);
}
voidCClientDlg:
:
ShowInDisplay(CStringstr)
{
m_strDisplay+=str+"\r\n";
UpdateData(FALSE);
}
voidCClientDlg:
:
ShowMessage(constNETMESSAGE&netMessage)
{
CStringstrTo=netMessage.to;
if(strTo==_T(""))
{
strTo="所有人";
}
elseif(strTo==m_strName)
{
strTo="你";
}
CStringstrForm=netMessage.form;
CStringstrMsg=netMessage.data;
CStringstrOut=strForm+"对"+strTo+"说:
"+strMsg;
ShowInDisplay(strOut);
}
voidCClientDlg:
:
OnDblclkListUser()
{
//TODO:
Addyourcontrolnotificationhandlercodehere
m_lbUser.SetCurSel(-1);
}
voidCClientDlg:
:
OnConnect()
{
m_bConnect=TRUE;
}
(二)服务端
服务器端聊天程序必须能够做3件事情:
(1)服务器聊天程序要在待定的端口上等待来自聊天客户的连接请求,并且需要维护一个客户连接表,以记录所有成功的连接。
(2)服务器聊天程序要及时接受从各个聊天客户发送过来的信息,然后把这些信息转发到一个或多个客户连接。
对于公共聊天室,服务器将把接受到的信息向除源端外的所有客户发送过去。
(3)服务器还要监控这些连接的状态,在客户主动离开或发生故障时从列表中删除相应的表项,并及时更新连接表。
服务端程序如下:
//ServerDlg.cpp:
implementationfile
//
#include"stdafx.h"
#include"Server.h"
#include"ServerDlg.h"
#ifdef_DEBUG
#definenewDEBUG_NEW
#undefTHIS_FILE
staticcharTHIS_FILE[]=__FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
//CAboutDlgdialogusedforAppAbout
classCAboutDlg:
publicCDialog
{
public:
CAboutDlg();
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg:
:
CAboutDlg():
CDialog(CAboutDlg:
:
IDD)
{
}
voidCAboutDlg:
:
DoDataExchange(CDataExchange*pDX)
{
CDialog:
:
DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg,CDialog)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//CServerDlgdialog
CServerDlg:
:
CServerDlg(CWnd*pParent/*=NULL*/)
:
CDialog(CServerDlg:
:
IDD,pParent)
{
m_hIcon=AfxGetApp()->LoadIcon(IDI_ICONAPP);
}
voidCServerDlg:
:
DoDataExchange(CDataExchange*pDX)
{
CDialog:
:
DoDataExchange(pDX);
DDX_Control(pDX,IDC_LIST_USER,m_lbUser);
DDX_Text(pDX,IDC_EDIT_DISPLAY,m_strDisplay);
}
BEGIN_MESSAGE_MAP(CServerDlg,CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BN_START,OnBnStart)
ON_BN_CLICKED(IDC_BN_CLOSE,OnBnClose)
ON_MESSAGE(WM_RECEIVE,OnReceive)
ON_MESSAGE(WM_CLIENTCLOSE,OnClientClose)
ON_MESSAGE(WM_ACCEPT,OnAccept)
ON_WM_DESTROY()
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//CServerDlgmessagehandlers
BOOLCServerDlg:
:
OnInitDialog()
{
CDialog:
:
OnInitDialog();
ASSERT((IDM_ABOUTBOX&0xFFF0)==IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX<0xF000);
CMenu*pSysMenu=GetSystemMenu(FALSE);
if(pSysMenu!
=NULL)
{
CStringstrAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if(!
strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARA
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 通信网 原理 实验 报告 编程 实现 聊天 程序