计算机控制系统设计报告ARM.docx
- 文档编号:15091230
- 上传时间:2023-06-30
- 格式:DOCX
- 页数:20
- 大小:343.80KB
计算机控制系统设计报告ARM.docx
《计算机控制系统设计报告ARM.docx》由会员分享,可在线阅读,更多相关《计算机控制系统设计报告ARM.docx(20页珍藏版)》请在冰点文库上搜索。
计算机控制系统设计报告ARM
《计算机控制系统》
PC-ARM网络通信系统
设计报告
姓名:
魏文
学号:
2011132065
指导教师:
范中磊
完成时间:
2011年12月28日
0引言
近年来,利用Internet进行网际间通讯,在WWW浏览、FTP、Gopher这些常规服务,以及在网络电话、多媒体会议等这些对实时性要求严格的应用中成为研究的热点,而且已经是必需的了。
Windows环境下进行通讯程序设计的最基本方法是应用WindowsSockets实现进程间的通讯,为此微软提供了大量基于WindowsSockets的通讯API,如WinSockAPI、WinInetAPI和ISAPI,并一直致力于开发更快、更容易的通讯API,将其和MFC集成在一起以使通讯编程越来越容易。
文中重点介绍了使用MFC的CSocket类编写PC端网络通讯程序的设计方法,并基于WindowsCE开发环境利用VS2005设计ARM端网络通讯程序。
1设计思路
MFC把复杂的WinSockAPI函数封装到类里,这使得编写网络应用程序更容易。
CAsyncSocket类逐个封装了WinSockAPI,为高级网络程序员提供了更加有力而灵活的方法。
这个类基于程序员了解网络通讯的假设,目的是为了在MFC中使用WinSock,程序员有责任处理诸如阻塞、字节顺序和在Unicode与MBCS间转换字符的任务。
为了给程序员提供更方便的接口以自动处理这些任务,MFC给出了CSocket类,这个类是由CAsyncSocket类继承下来的,它提供了比CAsyncSocket更高层的WinSockAPI接口。
Csocket类和CsocketFile类可以与Carchive类一起合作来管理发送和接收的数据,这使管理数据收发更加便利。
CSocket对象提供阻塞模式,这对于Carchive的同步操作是至关重要的。
阻塞函数(如Receive()、Send()、ReceiveFrom()、SendTo()和Accept())直到操作完成后才返回控制权,因此如果需要低层控制和高效率,就使用CasyncSock类;如果需要方便,则可使用Csocket类。
一些网络应用程序(如网络电话、多媒体会议工具)对实时性要求非常强,要求能够直接应用WinSock发送和接收数据。
为了充分利用MFC的优势,首选方案应当是MFC中的CAsyncSocket类或CSocket类,这两个类完全封装了WinSockAPI,并提供更多的便利。
本实例介绍应用这两个类的编程模型,并引出相关的成员函数与一些概念的解释。
CSocket类是由CAsyncSocket继承而来的,事实上,在MFC中CAsyncSocket逐个封装了WinSockAPI,每个CAsyncSocket对象代表一个WindowsSocket对象,使用CAsyncSocket类要求程序员对网络编程较为熟悉。
相比起来,CSocket类是CAsyncSocket的派生类,继承了它封装的WinSockAPI。
一个CSocket对象代表了一个比CAsyncSocket对象更高层次的WindowsSocket的抽象,CSocket类与CSocketFile类和CArchive类一起工作来发送和接收数据,因此使用它更加容易使用。
CSocket对象提供阻塞模式,因为阻塞功能对于CArchive的同步操作是至关重要的。
在这里有必要对阻塞的概念作一解释:
一个socket可以处于"阻塞模式"或"非阻塞模式",当一个套接字处于阻塞模式(即同步操作)时,它的阻塞函数直到操作完成才会返回控制权,之所以称为阻塞是因为此套接字的阻塞函数在完成操作返回之前什么也不能做。
如果一个socket处于非阻塞模式(即异步操作),则会被调用函数立即返回。
在CAsyncSocket类中可以用GetLastError成员函数查询最后的错误,如果错误是WSAEWOULDBLOCK则说明有阻塞,而CSocket绝不会返回WSAEWOULDBLOCK,因为它自己管理阻塞。
微软建议尽量使用非阻塞模式,通过网络事件的发生而通知应用程序进行相应的处理。
但在CSocket类中,为了利用CArchive处理通讯中的许多问题和简化编程,它的一些成员函数总是具有阻塞性质的,这是因为CArchive类需要同步的操作。
在Win32环境下,如果要使用具有阻塞性质的套接字,应该放在独立的工作线程中处理,利用多线程的方法使阻塞不至于干扰其他线程,也不会把CPU时间浪费在阻塞上。
多线程的方法既可以使程序员享受CSocket带来的简化编程的便利,也不会影响用户界面对用户的反应。
1.1CAsyncSocket类编程模型
在一个MFC应用程序中,要想轻松处理多个网络协议,而又不牺牲灵活性时,可以考虑使用CAsyncSocket类,它的效率比CSocket类要高。
CAsyncSocket类针对字节流型套接字的编程模型简述如下:
(1)构造一个CAsyncSocket对象,并用这个对象的Create成员函数产生一个Socket句柄。
可以按如下两种方法构造:
CAsyncSocketsock;//使用默认参数产生一个字节流套接字
Sock.Create();
或在指定端口号产生一个数据报套接字
CAsyncSocket*pSocket=newCAsyncSocket;
intnPort=27;
pSocket->Create(nPort,SOCK-DGRAM);
第一种方法在栈上产生一个CAsyncSocket对象,而第二种方法在堆上产生CAsyncSocket对象;第一种方法中Create()成员函数用缺省参数产生一个字节流套接字,第二种方法中用Create()成员函数在指定的端口产生一个数字报套接字。
Create()函数的原型为:
BOOLCreate(UINTnSocketPort=0,intnSocketType=SOCK_STREAM,
LPCTSTRlpszSocketAddress=NULL);
该函数的参数有:
1)端口,UINT类型。
注意:
如果是服务方,则使用一个众所周知的端口供服务方连接;如果是客户方,典型做法是接受默认参数,使套接字可以自主选择一个可用端口;2)socket类型,可以是SOCK-STREAM(默认值,字节流)或SOCK-DGRAM(数据报);3)socket的地址,例如"202.193.64.33"。
(2)如是客户方程序,用CAsyncSocket∷Connect()成员函数连接到服务方;如是服务方程序,用CAsyncSocket∷Listen()成员函数开始监听,一旦收到连接请求,则调用CAsyncSocket∷Accept()成员函数开始接收。
注意:
CAsyncSocket∷Accept()成员函数要用一个新的并且是空的CAsyncSocket对象作为它的参数,这里所说的"空的"指的是这个新对象还没有调用Create()成员函数。
(3)调用其他的CAsyncSocket类的Receive()、ReceiveFrom()、Send()和SendTo()等成员函数进行数据通信。
(4)通讯结束后,销毁CAsyncSocket对象。
如果是在栈上产生的CAsyncSocket对象,则对象超出定义的范围时自动被析构;如果是在堆上产生,也就是用了new这个操作符,则必须使用delete操作符销毁CAsyncSocket对象。
1.2CSocket类编程模型
使用CSocket对象涉及CArchive和CSocketFile类对象。
以下介绍的针对字节流型套接字的操作步骤中,只有第3步对于客户方和服务方操作是不同的,其他步骤都相同。
(1)构造一个CSocket对象。
(2)使用这个对象的Create()成员函数产生一个socket对象。
在客户方程序中,除非需要数据报套接字,Create()函数一般情况下应该使用默认参数。
而对于服务方程序,必须在调用Create时指定一个端口。
需要注意的是,Carchive类对象不能与数据报(UDP)套接字一起工作,因此对于数据报套接字,CAsyncSocket和CSocket的使用方法是一样的。
(3)如果是客户方套接字,则调用CAsyncSocket∷Connect()函数与服务方套接字连接;如果是服务方套接字,则调用CAsyncSocket∷Listen()开始监听来自客户方的连接请求,收到连接请求后,调用CAsyncSocket∷Accept()函数接受请求,建立连接。
请注意Accept()成员函数需要一个新的并且为空的CSocket对象作为它的参数,解释同上。
(4)产生一个CSocketFile对象,并把它与CSocket对象关联起来。
(5)为接收和发送数据各产生一个CArchive对象,把它们与CSocketFile对象关联起来。
切记CArchive是不能和数据报套接字一起工作的。
(6)使用CArchive对象的Read()、Write()等函数在客户与服务方传送数据。
(7)通讯完毕后,销毁CArchive、CSocketFile和CSocket对象。
2PC端通讯程序设计
(1)启动VisualStudio2010,创建一个基于对话框架的MFC应用程序项目,将该项目命名为"Test";在MFC向导中选中Windows套接字;
(2)在对话框中按照实际需要添加控件,添加控件如表2-1;
表2-1
控件类型
控件ID
Caption属性
控件变量
变量类型
按钮
IDC_CONNECTBUTTON
连接
-
-
按钮
IDC_DISCONNECTBUTTON
断开
-
-
按钮
IDC_SENDBUTTON
发送
-
-
按钮
IDC_SENDCLEARBUTTON
清除发送
-
-
按钮
IDC_RECEIVECLEARBUTTON
删除
-
-
按钮
IDCANCEL
退出程序
-
-
编辑框
IDC_IPADDRESS
无
m_IPAddress
CString
编辑框
IDC_PORT
无
m_Port
UINT
编辑框
IDC_OUTPUTEDIT
无
m_Output
CString
编辑框
IDC_CONNECTEDIT
无
m_Connect
CString
列表框
IDC_INPUTEDIT
无
m_Iutput
CListBox
单选按钮
IDC_SERVERRADIO
服务器
m_Status
int
单选按钮
IDC_CLIENTRADIO
客户端
-
-
编辑框控件IDC_CONNECTEDIT属性“ReadOnly”值为“True”;IDC_SERVERRADIO属性“Group”值为“True”。
(3)使用ClassWizard为应用程序的按钮添加鼠标单击消息响应函数;
/*********************连接按钮消息处理函数******************/
voidCTestDlg:
:
OnConnect()
{
//TODO:
Addyourcontrolnotificationhandlercodehere
CStringmsg;
UpdateData(TRUE);
if(m_Status==0)//server
{
if(m_ServerSocket!
=NULL)
{
m_Connect="请断开连接!
";
UpdateData(FALSE);
}
else
{
m_Connect="等待连接...";
UpdateData(FALSE);
if(!
AfxSocketInit())
{
MessageBox(_T("WindowsSocket初始化失败!
"),_T("发送"),MB_ICONSTOP);
return;
}
m_ServerSocket=newCNewSocket;
m_ServerSocket->m_Status=m_Status;
m_ServerSocket->GetDlg(this);
if(!
m_ServerSocket->Create(m_Port))
MessageBox(_T("SendSocket创建失败!
"),_T("发送"),MB_ICONSTOP);
else
{
m_ServerSocket->Listen();
}
}
}
else
{
if(m_Status==1)//Client
{
if(m_ClientSocket!
=NULL)
{
m_Connect="请断开连接!
";
UpdateData(FALSE);
}
else
{
m_Connect="连接服务器...";
UpdateData(FALSE);
if(!
AfxSocketInit())
{
MessageBox(_T("WindowsSocket初始化失败!
"),_T("接收"),MB_ICONSTOP);
return;
}
m_ClientSocket=newCNewSocket;
m_ClientSocket->GetDlg(this);
m_ClientSocket->m_Status=m_Status;
if(!
m_ClientSocket->Create())
{
MessageBox(_T("ReceiveSocket创建失败!
"),_T("接收"),MB_ICONSTOP);
return;
}
else
{
if(!
m_ClientSocket->Connect(m_IPAddress,m_Port))
{
CStringstr=m_Connect;
SocketReset();
m_Connect=str;
m_Connect+="失败!
";
UpdateData(FALSE);
}
else
{
m_Connect+="完成!
";
m_file=newCSocketFile(m_ClientSocket);
m_arIn=newCArchive(m_file,CArchive:
:
load);
m_arOut=newCArchive(m_file,CArchive:
:
store);
}
UpdateData(FALSE);
}
}
}
}
if(m_Status==-1)
{
msg="请选择模式!
";
AfxMessageBox(msg);
}
}
/*********************断开按钮消息处理函数******************/
voidCTestDlg:
:
OnDisconnect()
{
//TODO:
Addyourcontrolnotificationhandlercodehere
if(m_arOut!
=NULL)
{
SocketReset();
m_Connect="已断开!
";
UpdateData(FALSE);
}
}
/*********************发送按钮消息处理函数******************/
voidCTestDlg:
:
OnSend()
{
//TODO:
Addyourcontrolnotificationhandlercodehere
if(m_arOut)
{
if(m_Status==0)
{
UpdateData(TRUE);
*m_arOut< m_arOut->Flush(); } else { UpdateData(TRUE); *m_arOut< m_arOut->Flush(); } } elseAfxMessageBox(_T("无有效连接! ")); } /*********************清除按钮消息处理函数******************/ voidCTestDlg: : OnSendclear() { //TODO: Addyourcontrolnotificationhandlercodehere m_Output=""; UpdateData(FALSE); } /*********************删除按钮消息处理函数******************/ voidCTestDlg: : OnReceiveclear() { //TODO: Addyourcontrolnotificationhandlercodehere m_Input.DeleteString(m_Input.GetCurSel()); UpdateData(FALSE); } /*********************服务器单选按钮消息处理函数******************/ voidCTestDlg: : OnServerradio() { //TODO: Addyourcontrolnotificationhandlercodehere UpdateData(TRUE); GetDlgItem(IDC_IPADDRESS)->EnableWindow(FALSE); GetDlgItem(IDC_PORT)->EnableWindow(TRUE); UpdateData(FALSE); } /*********************客户端单选按钮消息处理函数******************/ voidCTestDlg: : OnClientradio() { //TODO: Addyourcontrolnotificationhandlercodehere UpdateData(TRUE); GetDlgItem(IDC_IPADDRESS)->EnableWindow(TRUE); GetDlgItem(IDC_PORT)->EnableWindow(TRUE); UpdateData(FALSE); } (4)使用ClassWizard在应用程序中定义新类CNewSocket,其基类选择为CSocket;重载NewSocket类的OnAccept()、OnReceive()、OnClose()函数;增加公有变量CTestDlg*m_dlg;intm_Status并添加一成员函数voidGetDlg(CTestDlg*dlg); voidCNewSocket: : OnAccept(intnErrorCode) { //TODO: 在此添加专用代码和/或调用基类 if(m_dlg->m_ClientSocket==NULL)m_dlg->OnAccept(); CSocket: : OnAccept(nErrorCode); } voidCNewSocket: : OnReceive(intnErrorCode) { //TODO: 在此添加专用代码和/或调用基类 m_dlg->OnReceive(); CSocket: : OnReceive(nErrorCode); } voidCNewSocket: : GetDlg(CTestDlg*dlg) { m_dlg=dlg; } voidCNewSocket: : OnClose(intnErrorCode) { //TODO: 在此添加专用代码和/或调用基类 m_dlg->OnClose(); CSocket: : OnClose(nErrorCode); } (5)为窗口类TestDlg添加5个公有成员变量: CSocketFile*m_file; CArchive*m_arOut; CArchive*m_arIn; CNewSocket*m_ServerSocket; CNewSocket*m_ClientSocket; 并添加公有4个成员函数: voidSocketReset(); voidOnClose(); voidOnReceive(); voidOnAccept(); 编写公有函数代码: voidCTestDlg: : SocketReset() { if(m_arIn! =NULL) { deletem_arIn; m_arIn=NULL; } if(m_arOut! =NULL) { deletem_arOut; m_arOut=NULL; } if(m_file! =NULL) { deletem_file; m_file=NULL; } if(m_ClientSocket! =NULL) { deletem_ClientSocket; m_ClientSocket=NULL; } if(m_ServerSocket! =NULL) { deletem_ServerSocket; m_ServerSocket=NULL; } m_Connect=""; UpdateData(FALSE); } voidCTestDlg: : OnClose() { if(m_ClientSocket->m_Status==0)m_Connect="客户端"; elsem_Connect="服务器"; m_Connect+="已断开! "; UpdateData(FALSE); } voidCTestDlg: : OnReceive() { CStringstr1,str2; *m_arIn>>str2; str1=_T("PC机: "); str1+=str2; m_Input.AddString(str1); m_Input.SetCurSel(m_Input.GetCount()-1); UpdateData(FALSE); } voidCTestDlg: : OnAccept() { //u_longiMode=1; m_Connect+="完成! "; UpdateData(FALSE); m_ClientSocket=newCNewSocket; //m_ClientSo
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 计算机控制 系统 设计 报告 ARM
![提示](https://static.bingdoc.com/images/bang_tan.gif)