局域网聊天程序设计.docx
《局域网聊天程序设计.docx》由会员分享,可在线阅读,更多相关《局域网聊天程序设计.docx(34页珍藏版)》请在冰豆网上搜索。
![局域网聊天程序设计.docx](https://file1.bdocx.com/fileroot1/2022-10/26/cdcd51b2-f475-4c37-af9b-7b6d1cc30138/cdcd51b2-f475-4c37-af9b-7b6d1cc301381.gif)
局域网聊天程序设计
青岛理工大学
C++面向对象课程设计报告
院(系):
计算机工程学院
专业:
软件工程
学生姓名
:
管巨伟
班级
软件132学号:
201307227
题目:
局域网聊天程序设计
起迄日期:
2015.6.29〜2015.7.10
设计地点:
计算机学院机房
指导教
师:
李传斌杨鑫
完成日期:
2015年7月10日
任务书
一、课程设计目的与要求
1.课程设计目的
面向对象程序设计作为一门软件设计的课程,具有极强的实践性,必须使学生具备灵活应用理论知识的能力及面向对象程序设计技能。
所以在《C++面向对象程序设计》课程学习完成后,安排课程设计教学环节。
通过课程设计,使学生实际掌握面向对象的程序设计方法,了解C++面向对象的设计方法与技巧,有效地、深刻地理解课程内容,体会理论、方法和设计原则;培养学生分析实际问题和解决问题的能力,使学生具备使用面向对象程序设计开发工具设计实际系统的能力。
2.课程设计要求
结构化程序设计使用的是功能抽象,面向对象程序设计不仅能进行功能抽象,而且能进行数据抽象。
“对象”实际上是功能抽象和数据抽象的统一。
C++语言的“对象”是“类”
的实例,程序设计的基础是设计类,所以类的有关概念都是重点,尤其要抓住抽象、封装、继承和多态性等要素。
面向对象程序设计的核心是类层次的设计。
而具体类的设计的重点是如何选择数据成员和成员函数。
根据数据成员和成员函数的特点,结合具体问题设计合适的类。
成员函数设计中的难点是选择函数类型及其参数传递方式。
开发系统离不开设计平台,学生应在掌握面向对象程序设计基础上,熟悉并能熟练使用面向对象程序设计开发平台,结合相关理论知识,进行相应系统开发。
二、课程设计内容
课程设计题目及要求
局域网聊天程序设计:
服务端设置,通过对客户端多个线程的监听,显示客户端的上线、下线,与客户端进行信息交流。
开启服务器是通过新建socket,绑定端口号,监听线程,等
待客户端连入。
创建动态数组,完成客户端的连入,存储客户端信息。
结束线程,完成对资源释放。
课程设计报告内容
一、需求分析
1.选做此课题或项的目的
开发此聊天程序旨在供个人聊天交流使用,进行多人并发聊天,交流思想见解,让使用
同时了解现今正在使用的交流软件的基础功能,
多个任务同时进行的原理,拓展自己的视野,含的交互式界面的实现及应用。
2.程序所实现的功能
客户端:
1获取输入的IP地址,2、获取通信的端口号,3、获取从服务器发来的信息,4、
给服务器发送用户自定义的数据。
服务端:
1、获取客户端IP地址,2、获取通信的端口号,3、记录客户端连入的台数,4、
向所有连入客户端发送消息,5、接收客户端发送过来的信息
其他:
进行网络的设置、关闭运行的程序、发送消息、系统托盘、系统托盘下对程序的显示和退出操作。
二、内容设计
1.根据所选题目,给出模块图
2.画出主程序及其主要模块的流程图
3.编写程序关键代码客户端的线程函数:
#include"stdafx.h"#include"ChatRoomDlg.h"
#include"Inc.h"
DWORDWINAPIConnectThreadFunc(LPVOIDpParam)
{
CChatRoomDlg*pChatRoom=(CChatRoomDlg*)pParam;//创建指向窗口的指针ASSERT(pChatRoom!
=NULL);//判断线程是否为创建成功pChatRoom->m_ConnectSock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
//创建socket并用一个变量保存
if(pChatRoom->m_ConnectSock==INVALID_SOCKET){//判断socket是否创建成功
AfxMessageBox(_T("新建Socket失败!
"));
returnFALSE;
}
CStringstrServIp;pChatRoom->GetDlgItemText(IDC_IP_ADDR,strServIp);//获得服务端IP地址intiPort=pChatRoom->GetDlgItemInt(IDC_CONNECT_PORT);//获得端口号if(iPort<=0||iPort>65535){
AfxMessageBox(_T("请输入合适的端口:
1-65535"));
goto__Error_End;
}
charszIpAddr[16]={0};//将宽字节转换成窄字节
USES_CONVERSION;strcpy_s(szIpAddr,16,T2A(strServIp));sockaddr_inserver;//提供服务端信息server.sin_family=AF_INET;
server.sin_port=htons(iPort);//转换并存储端口server.sin_addr.s_addr=inet_addr(szIpAddr);//转换并存储IP地址if(connect(pChatRoom->m_ConnectSock,(structsockaddr*)&server,sizeof(structsockaddr))==SOCKET_ERROR){
AfxMessageBox(_T("连接失败,请重试!
"));goto__Error_End;
}pChatRoom->m_bIsServer=FALSE;//用于判断后面发送消息的是客户端pChatRoom->ShowMsg(_T("系统信息:
连接服务器成功!
"));while(TRUE&&!
(pChatRoom->bShutDown)){
if(SOCKET_Select(pChatRoom->m_ConnectSock)){TCHARszBuf[MAX_BUF_SIZE]={0};
intiRet=recv(pChatRoom->m_ConnectSock,(char*)szBuf,MAX_BUF_SIZE,0);//收取数据if(iRet>0){//连接成功
pChatRoom->ShowMsg(szBuf);
}else{//连接失败
pChatRoom->ShowMsg(_T("聊天室服务器已停止,请重新进行连接!
"));break;
}
}
Sleep(500);
}
__Error_End:
closesocket(pChatRoom->m_ConnectSock);//关闭线程returnTRUE;
}
服务端的线程函数:
#include"stdafx.h"
#include"ChatRoomDlg.h"
BOOLSOCKET_Select(SOCKEThSocket,intnTimeOut,BOOLbRead)//去缓冲区中查看是否有socket连接
{
fd_setfdset;
timevaltv;//超时时间FD_ZERO(&fdset);//清0FD_SET(hSocket,&fdset);
nTimeOut=nTimeOut>1000?
1000:
nTimeOut;
tv.tv_sec=0;//以秒为单位
tv.tv_usec=nTimeOut;//一毫秒为单位
intiRet=0;
if(bRead){
iRet=select(0,&fdset,NULL,NULL,&tv);//监听可读文件}else{
iRet=select(0,NULL,&fdset,NULL,&tv);//监听可写
}
if(iRet<=0){
returnFALSE;
}elseif(FD_ISSET(hSocket,&fdset)){//查看缓冲区中的socket是否准备好returnTRUE;
}
returnFALSE;
}
DWORDWINAPIListenThreadFunc(LPVOIDpParam)
{
CChatRoomDlg*pChatRoom=(CChatRoomDlg*)pParam;//创建窗口指针ASSERT(pChatRoom!
=NULL);//判断线程是否创建成功
pChatRoom->m_ListenSock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//创
//建socket并用一个变量保存
if(pChatRoom->m_ListenSock==INVALID_SOCKET){//如果创建的socket是无效套接字
AfxMessageBox(_T("新建Socket失败!
"));
returnFALSE;
}
intiPort=pChatRoom->GetDlgItemInt(IDC_LISTEN_PORT);
if(iPort<=0||iPort>65535){
AfxMessageBox(_T("请输入合适的端口:
1-65535"));
goto__Error_End;
}
sockaddr_inservice;//定义结构储存IP,端口号用于bind
service.sin_family=AF_INET;
service.sin_addr.s_addr=INADDR_ANY;
service.sin_port=htons(iPort);
if(bind(pChatRoom->m_ListenSock,(sockaddr*)&service,sizeof(sockaddr_in))==
SOCKET_ERROR){//判断绑定端口是否成功
AfxMessageBox(_T("绑定端口失败!
"));
goto__Error_End;
}
if(listen(pChatRoom->m_ListenSock,5)==SOCKET_ERROR){//判断监听端口是否成功
AfxMessageBox(_T("监听失败!
"));
goto__Error_End;
}
pChatRoom->ShowMsg(_T("系统信息:
启动服务器成功!
"));
pChatRoom->m_bIsServer=TRUE;//用于判断后面发送消息的是服务端pChatRoom->EnableWindow(IDC_START_SERVER,FALSE);//隐藏窗口pChatRoom->EnableWindow(IDC_STOP_SERVER);
while(TRUE&&!
(pChatRoom->bShutDown)){//为了连接多个客户端
if(SOCKET_Select(pChatRoom->m_ListenSock,100,TRUE)){//查看缓冲区中是否
//有连接的客户端sockaddr_inclientAddr;//定义变量供accept使用intiLen=sizeof(sockaddr_in);
SOCKETaccSoc