中国石油大学(华东)VC实验报告实验八
- 格式:docx
- 大小:199.29 KB
- 文档页数:9
中国石油大学(华东)自动化专业VC 实验报告
班级: 自动化1602 姓名: 谢清涛 学号: 1605010224
实验八 Windows 网络通信应用编程
一、实验目的
1、熟悉 Visual Studio 开发环境;
2、掌握 MFC 程序中菜单资源的设计方法;
3、掌握 socket 通信的基本概念和 socket 通信
MFC 类的编程方法;
二、实验内容
如图所示,创建单文档应用程序,实现 TCP 通信服务器和客户端功能。 设计要求:
(1) TCP 服务器方面,创建启动监听、停止监听和发送数据三个按钮,实现 TCP 服务器的监听
功能和通信功能;
(2) TCP 客户端方面,创建建立连接、断开连接和发送数据三个按钮,实现 TCP 客户端的连接
功能和通信功能;
实验日期: 成 绩:
三、实验报告
(1) 总结TCP 通信的基本流程;
A、服务器初始化——LISTEN
(1)调用socket函数创建文件描述符。
(2)调用bind函数将当前的文件描述符和ip/port绑定在一起。如果这个端口已经被其他进程占用了,就会bind失败。
(3)调用listen函数声明当前这个文件描述符作为一个服务器的文件描述符,为accept做好准备。(4)调用accept函数阻塞等待客户端连接起来。
B、建立连接的过程——三次握手
第一次:调用connect函数发出SYN段向服务器发起连接请求,并阻塞等待服务器应答。
第二次:服务器收到客户端的SYN段后,会应答一个SYN-ACK段表示“同一建立连接”。
第三次:服务器端收到SYN-ACK后会从connect函数中返回,同时应答一个ACK段。
C、数据传输的过程
建立连接后,TCP协议提供全双工的通信服务。所谓全双工,意思是:在同一条链路中的同一时刻,通信双方可以同时写数据。相对的概念叫做半双工,即:在同一条链路中的同一时刻,只能由一方来写数据。
(1)服务器从accept函数返回后立刻调用read函数读socket里的数据。读socket就像读管道一样,如果没有数据到达就阻塞等待。
(2)客户端调用write函数发送请求给服务器,服务器收到后就向客户端回复ACK,并从read函数中返回,对客户端的请求进行处理。在此期间客户端调用read函数阻塞等待服务器的应答。(3)服务器调用write函数将处理结果发回客户端,客户端收到后就回复ACK。服务器再次调用read函数阻塞等待下一条请求,。
(4)客户端从read函数中返回,并发送下一条请求,如此循环下去。
D、断开连接的过程——四次挥手
第一次:如果客户端没有更多的请求就调用close函数关闭连接,客户端会向服务器端发送FIN端。第二次:服务器收到FIN后会回应一个ACK,同时read返回0。
第三次:客户端收到FIN后,再返回一个ACK给服务器。
(2) 列出实现TCP 服务器端功能的代码清单;
CMyServer::CMyServer()
{
}
CMyServer::~CMyServer()
{
CMySocket *pSocket;
POSITION pos = m_ClientList.GetHeadPosition();
while(pos)
{
pSocket = (CMySocket*)m_ClientList.GetNext(pos);
pSocket->Close();
delete pSocket;
pSocket = NULL;
}
m_ClientList.RemoveAll();
}
void CMyServer::OnAccept(int nErrorCode)
{
CMySocket *pSocket = new CMySocket();
if(Accept(*pSocket))
{
m_ClientList.AddTail(pSocket);
pSocket->AsyncSelect(FD_READ|FD_CLOSE);
pSocket->SetMsgPara(m_pWnd,m_nMsgID);
pSocket->m_bAccept = TRUE;
m_pWnd->SendMessage(m_nMsgID, DAQ_LINK_ACCEPT,(LPARAM)pSocket);
}
else
{
delete pSocket;
pSocket = NULL;
}
}
void CMyServer::BroadcastData(BYTE TxData[], int len)
{
CMySocket *pSocket;
POSITION pos = m_ClientList.GetHeadPosition();
while(pos)
{
pSocket = (CMySocket*)m_ClientList.GetNext(pos);
pSocket->SendData(TxData,len);
}
}
BOOL CMyServer::SendData(BYTE TxData[], int len, CMySocket *pSocket)
{
CMySocket *m_pSocket;
POSITION pos = m_ClientList.GetHeadPosition();
while(pos)
{
m_pSocket = (CMySocket*)m_ClientList.GetNext(pos);
if(m_pSocket == pSocket)
{
m_pSocket->SendData(TxData,len);
}
}
return TRUE;
}
void CMyServer::ReadData(BYTE RxData[], int &len, CMySocket *pSocket)
{
if(pSocket != NULL)
{
len = pSocket->ReadData(RxData);