河北工业大学VisualC++的聊天室程序设计报告.docx
- 文档编号:18356840
- 上传时间:2023-08-16
- 格式:DOCX
- 页数:18
- 大小:290.70KB
河北工业大学VisualC++的聊天室程序设计报告.docx
《河北工业大学VisualC++的聊天室程序设计报告.docx》由会员分享,可在线阅读,更多相关《河北工业大学VisualC++的聊天室程序设计报告.docx(18页珍藏版)》请在冰点文库上搜索。
河北工业大学VisualC++的聊天室程序设计报告
河北工业大学
计算机C++课程设计
题目:
基于VisualC++的聊天室程序设计
姓名:
孟蕾
学号:
103336
班级:
计算机S102
指导教师:
李玉海
专业:
计算机科学与技术
2010年6月26日
】
1.引言
计算机网络技术发展至今已经大大超越了人们当初的预想,无论是人们日常的工作还是学习,我们都越来越多的依靠到互联网。
各种实时性的聊天娱乐软件也同时诞生,而且为我们的即时通讯带来了众多的方便,比如说大家所熟知的腾讯QQ、微软的MSN、移动的Fetion等,都是做的比较成功的实时聊天工具。
随着网络的日益普及,各种聊天工具也层出不穷,但当我们学习了《TCP/IP协议与网络编程》这门课程之后,我们便会觉得,其实要实现简单的网络通讯其实并不难。
接下来的课程设计就是针对一个简单的网络聊天程序,利用MFC为开发工具,实现基本的通讯功能。
1.1聊天室程序的开发背景
近年来,互连网发展日新月异,网络使空间的距离不再成为人们沟通的障碍,世界各个角落的人们可以通过Internet收发邮件、实时聊天、获取最新的资讯。
因此本次毕业设计以“面向连接的Winsock网络会话程序开发”为题,制作一个C/S聊天室程序,通过制作该程序还能更好的学习网络socket编程的相关知识。
1.2聊天室的设计目标
本课题是建立聊天通信模型,设计一个聊天室软件,包括服务器端和客户端,主要功能为:
服务器端功能:
1、初始化socket,创建服务器端。
2、维护一个链表,保存所有用户的IP地址、端口信息。
3、接受用户传送来的聊天信息,然后向链表中的所用用户转发。
4、接受用户传送来的连接判断命令,并向用户发出响应命令。
客户端功能:
客户端界面上的两个文本框,一个用于显示接受的聊天信息,一个用来接受用户输入的聊天信息。
当按下“发送”按钮时将信息发送给服务器。
通过本课题的毕业设计,可以比较深入的了解和掌握WINSOCK控件基本属性、方法和事件,理解网络聊天通信的概念,输控制协议(TCP)进行数据交流,初步掌握网络聊天通信程序的设计方法。
并能巩固和扩展大学期间的学习内容,进行项目的设计开发训练,更好的适应社会的需求。
2.总体设计
2.1功能要求
✧支持多个客户端的连接,在服务器和多个客户端之间进行数据传输;
✧接收客户端发送的消息,并显示在一个列表框中;
✧在用户连接上后有提示,显示出连接的用户名字;
✧发送信息时可以显示聊天的所有记录;
2.2系统主要功能和主要功能描述:
服务器端聊天程序必须能够做3件事情:
(1)服务器聊天程序要在待定的端口上等待来自聊天客户的连接请求,并且需要维护一个客户连接表,以记录所有成功的连接。
(2)服务器聊天程序要及时接受从各个聊天客户发送过来的信息,然后把这些信息转发到一个或多个客户连接。
对于公共聊天室,服务器将把接受到的信息向除源端外的所有客户发送过去。
(3)服务器还要监控这些连接的状态,在客户主动离开或发生故障时从列表中删除相应的表项,并及时更新连接表。
这些要求可以通过CSocket类提供的功能实现。
从CSocket派生出两个类CListenSocket和CClientSocket,它们分别用来侦听客户的连接请求和建立与客户的连接。
服务器只需要一个侦听套接字CListenSocket,然后根据客户的连接请求动态创建客户套接字CClientSocket。
客户套接字的数量是不可预知的,因此需要一个列表来记录。
MFC的CPtrList类就能实现这种功能。
客户端聊天程序需要完成以下几个功能:
(1)客户端聊天程序要负责建立和维护与服务器的连接,通过获取用户的设置尝试与服务器的连接,并且随时检测连接的状态。
(2)客户端聊天程序要把用户输入的信息及时发送到聊天服务器。
一般情况下,当用户输入一行信息并且按下回车键后聊天程序就要把这一行信息发送出去,才能及时地满足用户的交互需求。
(3)要随时准备好接受来自服务器的信息,随时把接受到的信息显示出来,让用户及时看到对方的响应。
(4)在用户退出聊天过程是要关闭与服务器的连接。
比较好的做法是提前通知服务器或者直接给服务器发送一条退出通知,使得服务器能够及时掌握客户端的连接状态,把对方客户的退出信息及时发送到对等实体上。
客户端聊天程序需要使用一个通过CSocket类派生出来的CChatSocket类来实现。
该套接字用来发送一个与服务器的连接请求和维持与服务器的连接,发送和接收聊天信息,完成上述各项功能。
3.详细设计
3.1设计流程图
3.2客户端的实现
(1)首先启动VisualC++6.0,利用MFCAppWizard[EXE]建立一个新的MFC工程,工程名为tcpclient,在MFCAppWizardStep1的时候选择Dialogbased即基于对话框。
(2)客户端主要分为三个窗口,第一个是连接窗口,需要输入连接到服务器的相关设置信息;第二个是聊天信息显示窗口,该窗口显示登录服务器以来发送和接收到的消息;第三个是消息编辑发送窗口,需要输入你要发送的信息内容并发送。
客户端界面图
新建一个对话框,并添加各种控件(见控件表3.12)如下图:
图3.12聊天窗口布局
表3.1控件类型及各自ID
标题
控件类型
控件ID
信息
Static
IDC_STATIC
聊天
Static
IDC_STATIC
发送的信息显示
Static
IDC_STATIC
欢迎您的到来
Static
IDC_STATIC
端口号(默认7788)
Static
IDC_STATIC
登陆
Button
IDC_LOGIN
注册
Button
IDC_REG
连接
Button
IDC_CONNECT
COMBO
COMBO
IDC_COMBO1
发送(回车)
Button
IDC_SEND
编辑框1
Edit
IDC_LISTEN_PORT_C
编辑框2
Edit
IDC_MESSAGE
编辑框3
Edit
IDC_REC
图片1
位图
IDC_STATIC
图片2
位图
IDC_STATIC
控件表3.12
(3)下面重点介绍一下单击连接服务器按钮时的处理网络连接的函数。
代码设置如下:
voidCSocketDlg:
:
OnConnect()
{
if(!
AfxSocketInit())
{
AfxMessageBox("IDC_SOCKET_INIT_FAILED");
return;
}
GetDlgItemText(IDC_IPADDRESS2,m_ipstr);
m_socket.m_hSocket=INVALID_SOCKET;
UpdateData(true);
BOOLflag=m_socket.Create();//创建套接字
if(!
flag)
{
AfxMessageBox("SOCKETERROR");
return;
}
m_socket.Connect(m_ipstr,m_port);
}设计步骤:
1)创建字符串ipstr(保存IP),portstr(保存端口),clientname(用户名),整型port(端口号)。
2)利用GetDlgItemText将各个编辑框中的信息赋给相应的变量。
3)创建套接字clconect,设置成功创建后相关控件为只读(避免误操作)。
4)设置建立连接后相应提示。
(4)接下来就是对话框中的发送(回车)按钮的函数,代码设置如下:
voidCSocketDlg:
:
OnSend()
{
intn;
CStrings,s1;
n=m_comoto.GetCurSel();
m_comoto.GetLBText(n,s);
CoInitialize(NULL);
_ConnectionPtrpconnect(__uuidof(Connection));
_RecordsetPtrrecord(__uuidof(Recordset));
_CommandPtrcomd(__uuidof(Command));
pconnect->ConnectionString="Provider=SQLOLEDB.1;IntegratedSecurity=SSPI;PersistSecurityInfo=False;InitialCatalog=user";
pconnect->Open("","","",NULL);
comd->put_ActiveConnection(_variant_t((IDispatch*)pconnect));
CStringcmda="";
cmda="select*fromtestwhereusername='";
cmda+=m_username;
cmda+="'andpassword='";
cmda+=m_password;
cmda+="'";
comd->CommandText=_bstr_t(cmda);//得到sql语句
if(m_username.IsEmpty()||m_password.IsEmpty())
{
AfxMessageBox("请输入用户或者密码");
CDialog:
:
OnOK();
return;
}
else
{
record=comd->Execute(NULL,NULL,adCmdText);//执行sql语句
}
if(!
record->end)
{
AfxMessageBox("登陆成功");
CSocketApp*pApp=(CSocketApp*)AfxGetApp();//得到应用程序的指针
CSocketDlg*pDlg=(CSocketDlg*)pApp->m_pMainWnd;//得到对话框的指针
pDlg->GetDlgItem(IDC_CONNECT)->EnableWindow(TRUE);
pDlg->GetDlgItem(IDOK)->EnableWindow(TRUE);
CDialog:
:
OnOK();
return;
//ShowWindow(0);
}
else
{
AfxMessageBox("没有该用户请先注册!
");
}
record->Close();
pconnect->Close();
comd.Release();
record.Release();
pconnect.Release();
CoUninitialize();
{
if(AfxMessageBox("用户名不能为空!
",MB_YESNO)==IDNO)
{
CDialog:
:
OnOK();
return;
}
else
{
return;
}
}
CDialog:
:
OnOK();
}
登陆界面如下:
(6)注册代码现实
voidCSocketDlg:
:
OnReg()
{
Registdlg;
CStringstr;
if(IDOK==dlg.DoModal()){}
voidRegist:
:
OnOK()
{
//添加到数据库
UpdateData(true);
CoInitialize(NULL);
_ConnectionPtrpconnect(__uuidof(Connection));
_RecordsetPtrrecord(__uuidof(Recordset));
_CommandPtrcomd(__uuidof(Command));
pconnect->ConnectionString="Provider=SQLOLEDB.1;IntegratedSecurity=SSPI;PersistSecurityInfo=False;InitialCatalog=user";
pconnect->Open("","","",NULL);
comd->put_ActiveConnection(_variant_t((IDispatch*)pconnect));
CStringcmda="";
cmda="select*fromtestwhereusername='";
cmda+=m_rname;
cmda+="'";
comd->CommandText=_bstr_t(cmda);//得到sql语句
record=comd->Execute(NULL,NULL,adCmdText);//执行sql语句
if(!
record->end)
{
AfxMessageBox("该用户名已经存在,请重新输入");
CDialog:
:
OnOK();
return;
}
cmda="insertintotestvalues('";
cmda+=m_rname;
cmda+="','";
cmda+=m_rpassword;
cmda+="')";
comd->CommandText=_bstr_t(cmda);//得到sql语句
if(m_rname.IsEmpty()||m_rpassword.IsEmpty())
{
AfxMessageBox("请输入用户或者密码");
CDialog:
:
OnOK();
return;
}
else
{
record=comd->Execute(NULL,NULL,adCmdText);//执行sql语句
}
AfxMessageBox("注册成功");
CDialog:
:
OnOK();
return;
if(!
record->end)
{
CSocketApp*pApp=(CSocketApp*)AfxGetApp();//得到应用程序的指针
CSocketDlg*pDlg=(CSocketDlg*)pApp->m_pMainWnd;//得到对话框的指针
pDlg->GetDlgItem(IDC_CONNECT)->EnableWindow(TRUE);
pDlg->GetDlgItem(IDOK)->EnableWindow(TRUE);
}
else
AfxMessageBox("REGISTERROR");
record->Close();
pconnect->Close();
comd.Release();
record.Release();
pconnect.Release();
CoUninitialize();
CDialog:
:
OnOK();
}
voidRegist:
:
OnReset()
{
UpdateData(0);
m_rname="";
m_rpassword="";
UpdateData
(1);
}
登陆界面如下:
(7)对文字字体和颜色的设置如下图:
代码如下:
voidCSocketDlg:
:
OnColor()
{
COLORREFinit(RGB(125,255,0));
CColorDialogdlg(init);
dlg.DoModal();
}
voidCSocketDlg:
:
OnFond()
{
CFontDialogdlg;
dlg.DoModal();
}
3.3服务端的实现
(1)和客户端一样,仍然建立一个基于对话框的工程,工程名为tcpserver,同样,注意一定不要忘记在Step4时勾选WindowsSockets选项。
其他默认下一步。
(2)客户端主要分为三个窗口,第一个是服务器信息设置窗口,需要输入服务器的相关设置信息;第二个是聊天信息显示窗口,该窗口显示启动服务器以来发送和接收到的消息;第三个是消息编辑发送窗口,需要输入你要发送的信息内容并发
图3.21
表3.2控件类型及各自ID
标题
控件类型
控件ID
信息发送
Static
IDC_STATIC
显示
Static
IDC_STATIC
创建服务器
Button
IDC_LISTEN
发送(回车)
Button
IDC_SEND
退出
Button
IDOK
编辑框1
Edit
IDC_PORT
编辑框2
Edit
IDC_sendmsg
编辑框3
Edit
IDC_msg
(3)下面重点介绍一下单击启动服务器按钮时的处理网络连接的函数。
代码设置如下:
voidCSerDlg:
:
OnListen()
{
UpdateData(true);
if(!
AfxSocketInit())
{
AfxMessageBox("IDP_SOCKETS_FAILED");
return;
}
BOOLflag=m_serversocket.Create(m_port);
if(!
flag)
{
AfxMessageBox("SOCKETERROR");
return;
}
flag=m_serversocket.Listen
(1);
if(!
flag)
{
AfxMessageBox("SOCKETERROR");
return;
}
SetDlgItemText(IDC_LISTEN,"正在监听");
}
(4)接下来就是对话框中的发送(回车)按钮的函数,代码设置如下:
voidCTcpseverDlg:
:
Onsend()
{
CStringstr,history;
GetDlgItemText(IDC_EDIT1,history);
GetDlgItemText(IDC_EDIT2,str);
str=severname+":
"+str;
intlen=str.GetLength();
intsended;
for(inti=1;i<=csnum;i++)if(csrev[i])
if(sended=csrev[i].Send(str,len)){
SetDlgItemText(IDC_EDIT2,"");SetDlgItemText(IDC_EDIT1,history+"\r\n"+str);
CEdit*ce=((CEdit*)GetDlgItem(IDC_EDIT1));
ce->LineScroll(ce->GetLineCount()-1);;}
}
(6)要显示服务器接收到来自客户端其他用户的信息,代码设置如下:
voidCTcpseverDlg:
:
onrev(intmynum)
{
CStringstr,str1;inti;
charss[100];
for(intj=0;j<100;j++)ss[j]='\0';
csrev[mynum].Receive(ss,100);
str.Format("%s",ss);
for(i=1;i<=csnum;i++)if(csrev[i])
if(csrev[i])csrev[i].Send(str,100);
GetDlgItemText(IDC_EDIT1,str1);
str=str1+"\r\n"+str;
SetDlgItemText(IDC_EDIT1,str);
CEdit*ce=((CEdit*)GetDlgItem(IDC_EDIT1));
ce->LineScroll(ce->GetLineCount()-1);;
}
(7)发送按钮的实现:
voidCSerDlg:
:
OnSend()
{
intilen;
intisent;
UpdateData(TRUE);
if(m_sendmsg!
="")
{
ilen=m_sendmsg.GetLength();
isent=m_serversocket.m_socket->Send(LPCTSTR(m_sendmsg),ilen);
if(isent==SOCKET_ERROR)
{
MessageBox("连接失败,请重试");
}
else
{
m_msg+="服务器"+m_sendmsg;
elseif(nCtlColor==CTLCOLOR_STATIC)//更改静态文本
{
pDC->SetTextColor(RGB(0,0,0));
pDC->SetBkColor(RGB(166,254,1));
HBRUSHb=CreateSolidBrush(RGB(166,254,1));
returnb;
}
elseif(nCtlColor==CTLCOLOR_DLG)//更改对话框背景色
{
pDC->SetTextColor(RGB(0,0,0));
pDC->SetBkColor(RGB(166,254,1));
HBRUSHb=CreateSolidBrush(RGB(166,254,1));
returnb;
}
}
至此服务器端的核心部分介绍完毕。
4.心得体会:
通过一周的课程设计,让我学会了很多东西,也算能比较熟练地掌握MFC这一个软件了,动手能力增强了不少。
参考文献:
VisualC++从入门到实践葛亮等编著
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 河北 工业大学 VisualC 聊天室 程序设计 报告