网络数据通信编程论文Word文件下载.docx
《网络数据通信编程论文Word文件下载.docx》由会员分享,可在线阅读,更多相关《网络数据通信编程论文Word文件下载.docx(25页珍藏版)》请在冰豆网上搜索。
远端通信目标
目标的网络ID
目标IP地址
目标主机名
获取/设置目标ID
获取/设置目标主机名
获取/设置目标IP地址
CDestination
对于用户与远端通信目标之间的交互信息,可以归纳为上下线通知、短消息、文件等3类(如下表所示),其属性都很简单,获取要传送的文件可以由MFC的CFileDialog类实现。
对用户与远端通信目标之间交互信息的分析
上下线通知
发送方ID
发送方主机名
消息类型(上线/下线)
无
MSG_NOTIFY
短消息
短消息内容
CMessage
文件
文件路径、文件名
获取文件路径、文件名
---
3.方法分析
可以将功能需求分为以下几部分。
(1) 在线状态管理
在线状态管理的内容包括:
上线时发送上线消息,在线时监听远端通信目标的状态,下线时则发送下线消息。
其UML活动图如下图
(2)所示。
其中的初始化包括创建界面窗口、加载WinSockCOM、加载系统配置文件、加载用户自身配置文件,系统的配置保存在bin/conf/config.xml文件中,用户自身配置文件保存在bin/conf/Profile.xml文件中。
(2)与远端通信目标的短消息通信
短消息通信是在在线状态下进行的,与监听远端通信目标状态、文件传输、信使服务
是并行的。
发送短消息需要指定接收方的远端通信目标。
短消息通信拥有自己的窗口,以便显示短消息内容和编辑发送的短消息。
其UML活动图如下图(3)所示。
图(2) 图(3)
(3)与远端通信目标的文件传输服务
文件传输也在在线状态下进行,也需要指定接收方的远端通信目标,通过CFileDialog查找要传递的文件,然后确认发送,就被发送到接收方的”..\File\”目录下。
其UML活动图如下图(4)所示。
(4)信使服务
信使服务用于与不经常联系的人进行通信服务,无需维护远端通信目标列表,只需输入对方的IP地址或主机名(局域网),就能发送简短消息,其UML活动图如下图(5)所示。
图(4) 图(5)
三:
界面设计
按照界面要求提出的需求,初步构想以下主要界面。
1.主界面
主界面分为与远端通信目标通信和信使服务两种状态,不使用时界面收缩到最小,不影响用户其他工作。
用列表来显示远端通信目标在线状态,目标上线则显示其网络名称,下线时则从列表中删除该目标,如下图(6)所示。
由于远端通信目标的短消息通信和发送文件都需要选择目标名,因此双击目标列表项即可打开一个新窗口(如图(7)所示),由于短消息通信及文件传输服务。
2.短消息及文件传输窗口
在此窗口中设置控件编辑消息、显示短消息内容,确认发送。
设置控件选取要传输的文件路径及文件名,可以直接使用CFileDialog。
此窗口仿照QQ及MSN的聊天窗口布置,如图(7)所示。
本例中限定短消息长少于128字(256Byte),因此可以用简短的Edit控件就可以了。
3.信使服务窗口
设置控件编辑短消息、输入计算机名或IP地址。
应考虑IP地址的特殊性(IP地址是点分16位数),此窗口布置如图(8)所示。
图(7)
图(6)
图(8)
四:
部分源代码
1.CMyessengerDlg类
voidCMyMessengerDlg:
:
ProcessOnlineMsg(CDestination*obj)
{
m_cs.Lock();
POSITIONpos=m_DestinationQueue.GetHeadPosition();
boolbExist=false;
for(;
pos!
=NULL;
m_DestinationQueue.GetNext(pos))
{
if(*m_DestinationQueue.GetAt(pos)==*obj)
{
bExist=true;
break;
}
}
if(bExist)
deleteobj;
else
m_DestinationQueue.AddTail(obj);
intnIndex=m_list.AddString(obj->
GetName());
//加到List中
if(LB_ERRSPACE==nIndex||LB_ERR==nIndex)
AfxMessageBox("
加到列表时出错!
"
);
TRACE("
加到列表时出错误!
\n"
ASSERT(FALSE);
else
m_list.SetItemDataPtr(nIndex,m_DestinationQueue.GetTailPosition());
m_cs.Unlock();
}
ProcessOfflineMsg(CDestination*obj)
deleteobj;
//删除对象
CDestination*pDeleted=m_DestinationQueue.GetAt(pos);
m_DestinationQueue.RemoveAt(pos);
//删除结点
if(!
pDeleted->
Get_pDlg())//删除短消息与文件传输窗口
pDeleted->
Get_pDlg()->
SetPeer((POSITION)NULL);
OnDestOffline(0,0);
//删除远端目标LIST上的条目,通过pos来找到.
for(inti=0;
i<
m_list.GetCount();
i++)
if(m_list.GetItemDataPtr(i)==pos)
{
m_list.DeleteString(i);
break;
}
//删除结点上的对象
deletepDeleted;
OpenChatDlg(POSITIONpos)
//锁定目标链表中的结点,以免被释放。
//取得指定的目标结点
CDestination*pObj=m_DestinationQueue.GetAt(pos);
CDlgChat*pDlg=pObj->
Get_pDlg();
if(!
pDlg)
//构造此目标的短消息与文件传输窗口
CStringstrRemoteIPAddress=pObj->
GetIPAddress();
CStringstrRemoteNickName=pObj->
GetName();
DWORDdwRemoteID=pObj->
GetID();
pDlg=CDlgChat:
CreateRelatedWnd(pos,dwRemoteID,strRemoteNickName,strRemoteIPAddress);
//将此结点与窗口绑定
m_DestinationQueue.GetAt(pos)->
Set_pDlg(pDlg);
pDlg->
ShowWindow(SW_RESTORE);
//显示窗口
SetForegroundWindow();
OnTimer(UINTnIDEvent)
SendOnlineMsg();
CDialog:
OnTimer(nIDEvent);
shortCMyMessengerDlg:
m_TransPort;
SendDestinationMsg(MSG_NOTIFYdgm)
TRACE("
BroadcastProfile开始...\n"
//使用UDP的socket,使用广播方式,MFC自动选择端口。
CWorkSocketwrkSocket;
BOOLbErr=wrkSocket.Create(0,SOCK_DGRAM);
bErr)
TRACE("
wrkSocket.Createerror(0x%x)\n"
GetLastError());
ASSERT(FALSE);
BOOLval=TRUE;
bErr=wrkSocket.SetSockOpt(SO_BROADCAST,&
val,sizeof(BOOL));
SetSockOpterror(0x%x)\n"
//将profile广播到其他机器的m_TransPort
intnErr=wrkSocket.SendTo(&
dgm,sizeof(dgm),
CMyMessengerDlg:
m_TransPort,NULL);
if(SOCKET_ERROR==nErr)
nErr=GetLastError();
SendToerror(0x%x)\n"
nErr);
//SendOK!
!
Broadcastprofileok!
wrkSocket.Close();
wrkSocket.ShutDown();
voidCMyMessengerDlg:
OnDblclkList()
//与指定目标收发短消息
intnIndex=m_list.GetCurSel();
if(LB_ERR==nIndex)
AfxMessageBox("
必须指定通信对象!
OpenChatDlg((POSITION)m_list.GetItemDataPtr(nIndex));
CloseChatDlg(POSITIONpos)
if(NULL!
=pos)
Set_pDlg(NULL);
LRESULTCMyMessengerDlg:
OnChatMsg(WPARAMwParam,LPARAMlParam)
CMessage*pDGram=(CMessage*)lParam;
if(pDGram)
CDestination*pObj=SearchDestination(pDGram->
m_dwNetMsgID);
if(pObj)
//此目标结点是否有短消息与文件传输窗口。
if(pObj->
Get_pDlg())
//交给短消息与文件传输窗口处理
pObj->
OnRecv(pDGram->
m_strMsg);
else
TRACE("
信息来自%u,:
%s\n"
pDGram->
m_dwNetMsgID,pDGram->
}
deletepDGram;
return0;
constCString&
CMyMessengerDlg:
GetSelfName()const
returnm_strSelfName;
constDWORD&
GetSelfID()const
returnm_dwSelfID;
2.在线短消息服务
voidCDlgChat:
SendMsg()
SendMsg()开始...\n"
//使用一个UDP的socket
CWorkSocketworkSocket;
BOOLbRet=workSocket.Create(0,SOCK_DGRAM);
charbuf[1024]={0};
//SetchatMsgheader
#pragmamessage("
-Author-Entityproblemsolved!
)
sprintf(buf,"
<
ChatDiagram>
"
NetMsgID>
%u<
/NetMsgID>
Msg>
%s<
/Msg>
/ChatDiagram>
m_dwSelfID
"
try
IXMLDOMDocumentPtrxmlDoc(__uuidof(DOMDocument));
xmlDoc->
async=false;
loadXML(_bstr_t(buf));
selectSingleNode("
ChatDiagram/Msg"
)->
text=(constchar*)m_strMsg;
strncpy(buf,xmlDoc->
xml,sizeof(buf));
catch(_com_error&
e)
CStringsError="
com_error:
"
;
sError+=(constchar*)e.Description();
AfxMessageBox(sError);
//向对方m_strPeerIP的shortChatPort上发送短消息XML
intnErr=workSocket.SendTo(buf,strlen(buf)+1
CDlgChat:
shortChatPort,m_strPeerIP);
boolbSendOK=(SOCKET_ERROR!
=nErr);
if(bSendOK)
Sendmessageerror(0x%x)\n"
Sendmessageok!
PostMessage(WM_CHAT_MSG,1,0);
workSocket.Close();
SaveMsg()
%s\n"
m_strSelfName);
SaveMsg(m_strSelfName,m_strMsg);
//#pragmamessage("
--OnRecv在收到对方短信息时,如果窗口没有打开,那么信息就不能被显示,这个要修改。
OnRecv(CStringstrMsg)
SaveMsg(m_strPeerName,strMsg);
intnLen=m_MsgNote.GetWindowTextLength();
//显示到短消息显示Edit末尾一行
m_MsgNote.SetSel(nLen,nLen);
CStringstrTemp=m_strPeerName+"
+strMsg+"
\r\n"
m_MsgNote.ReplaceSel(strTemp);
OnSend()
UpdateData(TRUE);
//禁止发送按钮和输入编辑框
m_Send.EnableWindow(FALSE);
m_Msg.EnableWindow(FALSE);
SendMsg();
//发送信息
SaveMsg();
//保存信息
intnLen=m_MsgNote.GetWindowTextLength();
//显示信息到最后一行。
m_MsgNote.SetSel(nLen,nLen);
CStringstrTemp=m_strSelfName+"
+m_strMsg+"
//清空输入框
m_strMsg="
UpdateData(FALSE);
SaveMsg(CStringspeaker,CStringstrMsg)
externCMyMessengerApptheApp;
CStringstrFileName;
strFileName.Format((theApp.GetWorkDIR()+"
chat\\%u"
),m_dwPeerID);
CStringstrPut=speaker+"
strPut+=strMsg+"
CStdioFilefile(strFileName,CFile:
modeCreate|CFile:
modeNoTruncate
|CFile:
modeWrite|CFile:
shareDenyWrite|CFile:
typeText);
file.SeekToEnd();
file.WriteString(strPut);
catch(CFileException&
e.ReportError();
shortCDlgChat:
shortChatPort=0;
PostNcDestroy()
{
删除短消息对话框。
m_strPeerName);
CMyMessengerDlg*pMainWnd=static_cast<
CMyMessengerDlg*>
(AfxGetMainWnd());
pMainWnd->
CloseChatDlg(m_posPeer);
ShutDownRelation();
PostNcDestroy();
deletethis;
OnClose()
//CMyMessengerDlg*pMainWnd=static_cast<
//pMainWnd->
//ShutDownRelation();
DestroyWindow();
3.文件传输服务
OnSendFiles()
CFileDialogdlg(TRUE);
if(IDOK==dlg.DoModal())
AfxMessageBox(dlg.m_ofn.lpstrFile);
SendFile(dlg.m_ofn.lpstrFile);
}
SendFile(CStringstrFileName)