网设.docx
- 文档编号:8957929
- 上传时间:2023-02-02
- 格式:DOCX
- 页数:23
- 大小:343.05KB
网设.docx
《网设.docx》由会员分享,可在线阅读,更多相关《网设.docx(23页珍藏版)》请在冰豆网上搜索。
网设
目录
第一章系统概述-2-
1.1系统目标-2-
1.2系统主要功能-2-
1.3TCP/IP体系结构-3-
1.4socket通信原理-4-
第二章总体结构设计-6-
2.1系统功能结构图-6-
2.2系统各功能模块说明-6-
2.2.1服务器端功能模块-6-
2.2.2客户端功能模块-6-
2.3系统流程图-7-
第三章代码设计-8-
3.1代码结构设计-8-
3.2程序设计-12-
3.2.1服务器端代码-12-
3.2.2客户端代码-14-
第四章输入输出设计-17-
4.1输入输出设计-17-
第五章处理过程设计-19-
5.1程序流程图-19-
5.1.1服务器端流程图-19-
5.1.2客户端流程图-20-
第六章总结-22-
6.1实验中主要问题-22-
Socket双机即时通信
05级信管魏志江指导教师王海涛
摘要:
本文通过理论联系实际,利用vc++工具,利用mfc封装的API类设计一个能实现最基本的多用户的双机通信程序,既聊天室,旨在阐述网络程序设计的基本过程,tcp/ip协议的应用开发,多线程的应用特点。
关键词:
通信sockettcp/ip
Abstract:
Bylinkingtheorywithpractice,theusevc++tools,usingtheAPIcategorymfcpackagedesigntoachievethemostbasicofamulti-userdual-machinecommunicationprocedures,bothchatrooms,designedtosetoutthebasicnetworkprogrammingprocess,tcp/ipagreementapplicationdevelopment,multi-threadedapplicationcharacteristics.
Keywords:
Communicationsockettcp/ip
第一章系统概述
1.1系统目标
本系统通过设计实现双击的即时通信,通过客户端和服务器端的两个子系统的设计来实现此功能,旨在进一步熟悉计算机网络的理论,灵活运用tcp和udp协议,通过程序了解其区别及其联系。
进一步掌握tcp/ip体系,能够利用socket来实现底层的通信,为以后的大型网络设计奠定一定的基础。
通过设计加深对计算机网络基本原理的认识,初步掌握计算机网络协议与体系结构实现,以及利用协议开发应用系统的方法,提高进行工程设计和系统分析的能力,随着网络的不断发展,网络设计不断的提出新的理论,我们通过掌握的基础的理论与实践,能够适应未知的网络世界,及网络新知识。
1.2系统主要功能
(1)系统概述
本系统主要功能为:
通过网络,由服务器端建立聊天室,用户可以通过安装客户端程序,用户可以查看各个聊天室房间的用户信息,根据自己的需求来选择加入单个房间,加入后可以和本房间的好友进行聊天,本系统通过为每个用户进行线程管理,充分利用的多线程的优点,本系统分为两部分:
服务器端和客户端。
(2)服务器端功能
服务器端可以建立聊天室,并且进行用户管理,可以给各个群发送一些公共信息,通知群中所有成员或者是单个个体、几个个体不等,管理员可以警告,处理规范聊天室的规范的单个成员。
(3)客户端功能
客户端可以浏览各个房间的成员数量以及成员信息,根据自己的兴趣来加入合适的房间,来和自己感兴趣的好友进行单独聊天。
用户可以根据需要可以隐藏自己的个人信息以便使在线的其他人无法得知,最后,用户可以退出房间或者直接加入别的房间。
1.3TCP/IP体系结构
图一:
tcp/ip体系结构
图二:
tcp/ip特点
1.4socket通信原理
(1)socket客户/服务器模式
在TCP/IP网络应用中,通信的两个进程间相互作用的主要模式是客户/服务器模式(Client/Servermodel),即客户向服务器发出服务请求,服务器接收到请求后,提供相应的服务。
客户/服务器模式的建立基于以下两点:
首先,建立网络的起因是网络中软硬件资源、运算能力和信息不均等,需要共享,从而造就拥有众多资源的主机提供服务,资源较少的客户请求服务这一非对等作用。
其次,网间进程通信完全是异步的,相互通信的进程间既不存在父子关系,又不共享内存缓冲区,因此需要一种机制为希望通信的进程间建立联系,为二者的数据交换提供同步,这就是基于客户/服务器模式的TCP/IP。
客户/服务器模式在操作过程中采取的是主动请求方式:
首先服务器方要先启动,并根据请求提供相应服务:
1.打开一通信通道并告知本地主机,它愿意在某一公认地址上(如FTP为21)接收客户请求。
2.等待客户请求到达该端口。
3.接收到重复服务请求,处理该请求并发送应答信号。
接收到并发服务请求,要激活一新进程来处理这个客户请求。
新进程处理此客户请求,并不需要对其它请求作出应答。
服务完成后,关闭此新进程与客户的通信链路,并终止。
4.返回第二步,等待另一客户请求。
5.关闭服务器。
客户方:
1.打开一通信通道,并连接到服务器所在主机的特定端口。
2.向服务器发服务请求报文,等待并接收应答;继续提出请求。
3.请求结束后关闭通信通道并终止。
从上面所描述过程可知:
1.客户与服务器进程的作用是非对称的,因此编码不同。
2.服务进程一般是先于客户请求而启动的。
只要系统运行,该服务进程一直存在,直到正常或强迫终止。
(2)面向连接的socket通信原理
WinSock提供了对TCP(传输控制协议)的支持,通过TCP协议我们可以与指定IP地址的主机建立,同时利用建立的连接可以双向的交换数据。
利用CSocket操纵有连接数据交换很简单,但是在有连接的通信中必须有一方扮演服务器的角色等待另一方(客户方)的连接请求,所以服务器方需要建立一个监听套接口,然后在此套接口上等待连接。
当连接建立后会产生一个新的套接口用于通信。
而客户方在创建套接口后只需要简单的调用连接函数就可以创建连接,对于有连接的通信不论是数据的发送还是发送与接收的顺序都是有保证的。
双方的函数调用如图三。
(3)套接口的功能
套接口类所提供的一些功能,通过这些功能我们可以方便地建立网络连接和发送数据。
1,Create(UINTnSocketPort=0,intnSocketType=SOCK_STREAM,longlEvent=FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT|FD_CLOSE,LPCTSTRlpszSocketAddress=NULL)用于创建一个本地套接口,其中nSocketPort为使用的端口号,为零则表示由系统自动选择,通常在客户端都使用这个选择。
nSocetType为使用的协议族,SOCK-STREAM表明使用有连接的服务,SOCK_DGRAM表明使用无连接的数据报服务。
2,BOOLBind(constSOCKADDR*lpSockAddr,intnSockAddrLen)作为等待连接方时产生一个网络半关联,或者是使用udp协议时产生一个网络半关联。
3,BOOLListen(intnConnectionBacklog=5)作为等待连接方时指明同时可以接受的连接数,请注意不是总共可以接受的连接数。
4,virtualBOOLAccept(CAsyncSocket&rConnectedSocket,SOCKADDR*lpSockAddr=NULL,
int*lpSockAddrLen=NULL)作为等待连接方将等待连接建立,当连接建立后一个新的套接字将被创建,该套接口将会被用于通信。
5,BOOLConnect(LPCTSTRlpszHostAddress,UINTnHostPort)作为连接方发起与等待连接方的连接,需要指明对方的IP地址和端口号。
6,virtualvoidClose()关闭套接口。
7,virtualintSend(constvoid*lpBuf,intnBufLen,intnFlags=0)
8,virtualintReceive(void*lpBuf,intnBufLen,intnFlags=0)在建立连接后发送和接收数据,nFlags为标记位,双方需要指明相同的标记。
(3)socket通信原理图
图三:
socket通信原理过程图
第二章总体结构设计
2.1系统功能结构图
图一:
系统总体功能图
2.2系统各功能模块说明
2.2.1服务器端功能模块
(1)添加房间功能
管理员可以根据实际需要添加房间,允许客户加入此房间来谈论相关话题。
(2)删除客户功能模块
管理员根据实际来删除每一个房间的客户。
(3)发公告功能
管理员首先选择要发送信息的房间,然后可以点击发用公告来通知本公告的所有成员,此外管理员也可以发送针对所有房间的公告来通知所有用户。
2.2.2客户端功能模块
(1)浏览功能
用户安装客户端后,可以浏览各个房间的信息,各个用户信息,并且可以通过输入用户名查找用户。
(2)加入房间功能
用户根据自己需要右单击选择加入房间,加入后就可以和此房间所有用户进行聊天。
(3)更改房间功能
当用户需求改变时,可以根据需要来重新选择放假并且加入之。
(4)聊天功能
当用户加入一个房间后可以选择要聊天的对象并且与其个人单独聊天。
2.3系统流程图
图二:
服务器端流程图
图三:
客户端流程图
第三章代码设计
3.1代码结构设计
(1)服务器端代码结构设计
表一:
应用程序类
说明:
1,此类是vc里面的应用程序类,在这里做一些工程的初始化工作,以便其他的类来使用。
2,在这里我们工作:
创建socket并且bind到ip地址及端口;监听是否有来访socket;当服务器关闭时向所有用户发送退出消息。
表二:
服务器socket类
说明:
1,此类继承自CSocket类
2,此类通过重载OnAccept类,来对监听的请求,进行接收工作。
表三:
消息路由类
说明:
此类封装自定义消息路由,根据定义的不同的事件对消息进行不同的响应,通过PostMessage方法把Message加入到消息处理。
表四:
操作客户端socket类
说明:
1,此类的主要是接收和发送消息就是与用户进行通信操作。
2,实现上述操作通过重载OnReceive和onSend类来实现通信功能。
3,获得和设置房间及用户,为工程的其他类判断做准备。
表五:
显示信息框架类
说明:
1,此类主要是提供显示信息平台,直接和用户交互,响应用户发出的消息,并把结果显示给用户。
2,主要相应有:
用户进入房间、用户退出房间、用户改变房间、用户发送消息。
表六:
公共文件类
说明:
1,此类主要功能是读取ini文件信息,
、识别ini文件内容信息、操作ini文件信息内容。
2,文件操作主要数据结构
CArray
通过数组类来存储信息,实现文件具体操作。
(2)客户端代码结构设计(主要控制类)
表七:
连接服务器类
说明:
此类用于设置要连接的服务器的IP地址和端口号、用户名并且把当前用户名写入客户端的ini文件。
表八:
客户端socket类
说明:
此类主要功能是通知正在监听的服务器端口有一个客户端将要通过此端口连接到服务器并且通过receive进行连接并同时获得设置用户的相关信息。
表九:
用户交互类
说明:
1,此类主要是提供显示信息平台,直接和用户交互,响应用户发出的消息,并把结果显示给用户。
2,并且即时响应当用户退出,加入房间时,把消息发送至服务器,服务器监听到此消息执行相应的操作。
表十:
接收发送消息类
说明:
此类主要操作在CShowMessage方法里面进行实现,当用户发送消息时使用socket的send方法。
3.2程序设计
3.2.1服务器端代码
(1)在App类里面进行基础的公共操作。
if(!
m_skServerSocket.Create(Dlg.m_iServerPort))//创建socket并且bind到ip地址及端口。
{
if(m_ChatRoomList.GetCount())
{
m_ChatRoomList.RemoveAll();
}
returnFALSE;
}
}
if(!
m_skServerSocket.Listen())//监听是否有来访socket。
{returnFALSE;
}
(2)设置端口号
DDX_Text(pDX,IDC_SERVERPORT,m_iServerPort);//关联端口设置变量
DDV_MinMaxInt(pDX,m_iServerPort,0,65536);//设置输入端口范围
说明:
其操作采用的是通过和控件关联变量的方法来设置端口号。
(3)重载onAccept方法
voidCServerSocket:
:
OnAccept(intnErrorCode)
{
g_cs.Lock();
CClientSocket*m_pNewClient=newCClientSocket();
ASSERT(m_pNewClient!
=NULL);
Accept(*m_pNewClient);
CMainFrame*pFrame=static_cast
}
(4)发送data给连接的所有socket
msObj->iType=USERLOG;
msObj->iSubType=USERLOGIN;
intiLen=strUsrName.GetLength();
iLen>20?
20:
iLen;
lstrcpy(msObj->strName,strUsrName.GetBuffer(iLen));
strUsrName.ReleaseBuffer();
iLen=strRoom.GetLength();
iLen>20?
20:
iLen;
lstrcpy(msObj->strRoom,strRoom.GetBuffer(iLen));
strRoom.ReleaseBuffer();
g_cs.Lock();
CPtrList*m_pClientList=theApp.m_pClientSocketList;
intiCount=m_pClientList->GetCount();
POSITIONpos=m_pClientList->GetHeadPosition();
if(pos)
{
for(inti=0;i
{
CClientSocket*m_pClientSocket=(CClientSocket*)(m_pClientList->GetNext(pos));
iLen=m_pClientSocket->Send(msObj,sizeof(Message));
Sleep(100);
}
}
g_cs.Unlock();
(5)一个客户加入房间时
voidCMyTreeView:
:
OnNewClientIn(WPARAMwParam,LPARAMlParam)
{
Message*msObj=(Message*)wParam;
CStringstrRoom=msObj->strRoom;
CStringstrUsrName=msObj->strName;
HTREEITEMhItem=m_Tree.GetChildItem(m_ParentItem);
while(hItem)
{
CStringstrNodeName=m_Tree.GetItemText(hItem);
if(strNodeName==strRoom)
{
m_Tree.InsertItem(strUsrName,0,1,hItem);
m_Tree.Expand(hItem,TVE_EXPAND);
break;
}
hItem=m_Tree.GetNextItem(hItem,1);
}
//通知所有用户
}
(6)客户退出房间时
voidCMyTreeView:
:
OnClientOut(WPARAMwParam,LPARAMlParam)
{
Message*msObj=(Message*)wParam;
CStringstrRoom=msObj->strRoom;
CStringstrUsrName=msObj->strName;
HTREEITEMhItem=m_Tree.GetChildItem(m_ParentItem);
BOOLbFind=FALSE;
while(hItem&&!
bFind)
{
CStringstrNodeName=m_Tree.GetItemText(hItem);
if(strNodeName==strRoom)
{
//查找用户名的那一项
HTREEITEMhChildItem=m_Tree.GetChildItem(hItem);
while(hChildItem)
{
CStringstrUserNode=m_Tree.GetItemText(hChildItem);
if(strUserNode==strUsrName)
{
m_Tree.DeleteItem(hChildItem);
m_Tree.Expand(hItem,TVE_EXPAND);
bFind=TRUE;
break;
}
hChildItem=m_Tree.GetNextItem(hChildItem,1);
}
}
hItem=m_Tree.GetNextItem(hItem,1);
}
//通知所有用户
}
3.2.2客户端代码
(1)连接服务器
if(m_skMainSocket.Connect(Dlg.m_strServerIp,Dlg.m_iServerPort))
{
MessagemsObj;
msObj.iType=FIRSTLOG;
msObj.iSubType=FIRSTTIME;
CStringstrTemp=Dlg.m_strUserName;
intiLen=strTemp.GetLength();
lstrcpy(msObj.strName,strTemp.GetBuffer(iLen));
strTemp.ReleaseBuffer();
m_skMainSocket.Send(&msObj,sizeof(Message));
m_skMainSocket.SetUserName(strTemp);
}
(2)重载OnReceive(intnErrorCode)方法
voidCMainSocket:
:
OnReceive(intnErrorCode)
{
CMainFrame*pFrame=static_cast
CWnd*pTreeView=(CWnd*)pFrame->GetTreeView();
MessagemsContent;
intiLen1=sizeof(msContent);intiLen2=sizeof(Message);
memset(&msContent,0,sizeof(msContent));
intiLen=Receive(&msContent,sizeof(msContent));
CParseMessageParse(pTreeView,msContent);
Parse.SWitchMessage();
CSocket:
:
OnReceive(nErrorCode);
}
(3)发送信息给对方
if(m_strMessage.GetLength())
{
MessagemsObj;
memset(&msObj,0,sizeof(Message));
msObj.iType=USERSESSION;
msObj.iSubType=SAYINPRIVATE;
CStringstrTemp=theApp.m_skMainSocket.GetRoomName();
intiLen=strTemp.GetLength();
lstrcpy(msObj.strRoom,strTemp.GetBuffer(iLen));
strTemp.ReleaseBuffer();
strTemp=m_strMessage;
iLen=strTemp.GetLength();
iLen>1024?
1024:
iLen;
lstrcpy(msObj.strContent,strTemp.GetBuffer(iLen));
strTemp.ReleaseBuffer();
theApp.m_skMainSocket.Send(&msObj,sizeof(Message));
//自己的名字
strTemp=theApp.m_skMainSocket.GetUserName();
iLen=strTemp.GetLength();
iLen>20?
20:
iLen;
lstrcpy(msObj.strName,strTemp.GetBuffer(iLen));
strTemp.ReleaseBuffer();
//说话对象的名字
strTemp=m_strClientName;
iLen=strTemp.GetLength();
iLen
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 网设.docx