




已阅读5页,还剩16页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
此文档收集于网络,如有侵权,请联系网站删除 目 录1. 引言12. TCP/IP协议概述13.TCP/IP协议的系统设计24.TCP/IP协议的系统实现35. 结论116. 详细设计代码12Windows平台下TCP/IP协议的设计与实现 1. 引言本文背景基于一个TCP/IP协议改进项目,项目要求通过改进TCP/IP协议拥塞控制算法 来提高无线网络环境下的数据吞吐量。目前的TCP协议在无线网络环境下无法区分出拥塞 丢包与误码丢包,根据这两种不同的丢包原因需要对TCP的窗口进行不同的调整,因此需 要对现有的TCP/IP协议进行改进。针对这个需求提供的一个解决方案就是自己开发出一套 TCP/IP协议以替代系统TCP/IP协议,但是并不需要实现整个TCP/IP协议族,重点实现TCP 与IP协议即可。2. TCP/IP协议概述TCP/IP协议是Internet的技术基础。Internet是一个广域网,是目前联通世界上绝大多 数国家和地区的全球性信息系统。在Internet上,可以实现低成本、高速率、交互式的信息 查询、信息发布、通讯联络以及协同作业等等现代化的工作、学习和生活。TCP/IP协议族通常分为四个层次,应用层、传输层、网络层和链路层。如图1所示:应用层(FTP, SMTP等)传输层(TCP,UDP等)网络层(IP, ICMP等)链路层(网卡驱动等)图1 TCP/IP协议族四层结构应用层向用户提供一组常用的应用程序,比如电子邮件(SMTP)、文件传输访问(FTP)、 远程登录(Telnet)等。传输层提供进程间端到端的通信。在TCP/IP协议族中,主要有两种不同的传输协议: 传输控制协议(TCP)和用户数据报协议(UDP)。TCP提供面向連接的、可靠的(没有数据重复 或丢失),全双的数据流传输服务。而UDP则提供的是不可靠的面向无连接的数据传输服 务,其可靠性应由上层应用程序来支持。网络层,主要负责数据包的分组及路由选择。在TCP/IP协议族中,网络层协议包括网际协议IP、互连网控制报文协议ICMP、地址转换协议ARP和反向地址转换协议RARR。链路层处于四层结构的最低层,负责接收IP数据报并通过网络发送之,或从网络上接 收物理帧,抽出IP数据报,交给IP层。通常包括网络设备驱动程序及网络接口卡等。3.TCP/IP协议的系统设计以Windows网络体系结构为基础,参照Windows DDK中关于网络协议驱动与传输驱 动接口 (TDI)的相关资料,以及考虑到与原有系统TCP/IP兼容,提出的设计方案如图2所示。图2 TCP/IP协议设计框图应用程序也就是根据协议开发的特定应用。这里是针对开发的TCP/IP协议编写的一个 FTP小应用程序,用来测试开发的协议。应用程序通过Wm32 API3接口将其操作转化成相 应的请求提交给TDI客户。传输驱动程序接口(TDI)客户是核心态的驱动程序。它的主要功能是完成上层应用 程序的请求,或者根据该请求产生相应的TDI操作,并将该操作传递给下层的TDI传输器。 TDI客户通过Win32 API接口与上层应用程序交互;通过TDI接口与下层TDI传输器进行交互。TDI传输提供者(TDI Transport Provider)又称为TDI传输器,NDIS协议驱动程序,以及协议驱动程序,是工作在核心态的协议驱动程序。其中TCP协议,IP协议,ARP协议 等都是在这个模块中实现。它通过TDI接口与上层的TDI客户进行交互;通过NDIS接口 与下层微端口驱动进行交互。NDIS下层微端口驱动程序是工作在核心态的驱动程序,它负责将TDI传输器接入至特 定的网络适配器。它通过NDIS接口与上下层进行交互。4.TCP/IP协议的系统实现由图2中可以看出,整个系统可分为四部分,应用程序、TDI客户、TDI传输器和下层 微端口驱动。事实上对于下层微端口驱动并不需要考虑,因为可以直接调用NDIS库函数将 数据转发到这层,处于这层上的驱动会自动将数据送出网络适配器。因此真正需要开发的也 就是上面三个部分。应用程序是用来实现简単文件传输的,因此考虑开发两个小应用程序, 一个为服务器端,一个为客户端,服务器端用来监听和处理来自客户端的连接请求。客户端 主要是向服务器端请求连接和发送数据。TDI客户负责将来自应用程序的请求进行相应的处 理之后转发给下层的TDI传输驱动。TDI传输驱动主要是实现TCP, IP等功能,并与下层的 NDIS接口进行交互。4.1 应用程序的实现 客户端可以通过本地的某个端口向对方发送数据。并显示一些错误状态。服务器端,可以指定在本地的某个端口监听连接请求,接收数据,并显示一些状态。实现:通过DeviceIOControl 及相应ControlCode 来将命令传输到下层的TDI 客户。主要接口函数:CreateFile 和DeviceIoControlCreateFile 函数原型:HANDLE CreateFile(LPCTSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile);lpFileName 在这里就是指向要操作的TDI 客户(驱动)的符号链接,符号链接是下层驱动程序对Win32 子系统可见的引用符号,也就是代表了一个下层的驱动。这个函数的功能是打开下层的TDI 客户,并返回该设备句柄,以后对设备的所有操作都是通过该句柄来引用。DeviceIoControl 函数原型:BOOL DeviceIoControl(HANDLE hDevice,DWORD dwIoControlCode,LPVOID lpInBuffer,DWORD nInBufferSize,LPVOID lpOutBuffer,DWORD nOutBufferSize,LPDWORD lpBytesReturned,LPOVERLAPPED lpOverlapped);hDevice 和dwIoControlCode 是这里最重要的两个参数。前者是前面CreateFile 返回的句柄,代表设备对象,在这里即是下层的TDI 客户,表明是对它进行操作;后者是I/O 控制码,表明要在该设备上进行的操作类型,如发送数据,这个控制码可以是自定义的。在应用程序调用了DeviceIoControl 之后就将操作请求提交给了处于系统内核中的TDI客户。4.2 TDI 客户的实现TDI 客户将上层应用程序发过来的I/O 请求包 (IRP)进行处理,能在本层处理的则处理后直接返回,需要底层继续完成的则先将当前的IRP 状态设置为挂起,然后重新设置一个IRP 移交给下层驱动继续处理。实现: 主要是TirdcTcpIoControlDispatch 派遣例程的实现。这个派遣例程与DeviceIoControl 函数相对应。其主要功能是根据应用程序的不同请求(携带在IRP 中的IoControlCode)进行不同的处理。只是这里需要额外考虑的是,需要在TDI 客户的该例程中事先判断下是对服务器端的TDI 客户操作还是针对客户端的TDI 客户进行操作。主要接口函数:XXX_IOControlDispatch,TdiBuildXXX 和IoCallDriver。XXX_IOControlDispatch 函数原型:NTSTATUSXXX_DeviceIoControl(IN PDEVICE_OBJECT pDeviceObject,IN PIRP pIrp);驱动程序中注册的派遣例程都是pDeviceObject 和pIrp 这两个参数,前面代表了要操作的设备对象,后者代表I/O 请求类型。pDeviceObject 在这里具体的是只指服务器端的TDI客户或客户端的TDI 客户。现在以服务器的TDI 客户为例,假设要对其进行一个监听操作,则此时IRP 中所携带的IoControlCode 则是一个代表监听操作的控制码。这个函数就是根据不同的控制码来决定要进行的操作直接完成IRP 或者是转发请求到下层。对于我们的协议来说,很多情况下TDI 客户是不能独立完成一个IRP 请求的,需要转发到下层也就是它的TDI 传输器来继续完成IRP 的。这个时候就会用到后面的两个重要函数TdiBuildXXX,和IoCallDriver 了。TdiBuildXXX 函数原型:根据 IO 控制码的不同,该函数的声明也稍有区别。仍旧接着前面的事例,TDI 客户不能够独自完成应用程序的监听请求,因此需要借助TdiBuildXXX 函数来生成相应的IRP,交给下层的TDI 传输器进行处理。这里的XXX 既代表不同的操作,对于监听来说,既是TdiBuildListen。其函数原型如下:VOIDTdiBuildListen(PIRP Irp,PDEVICE_OBJECT DevObj,PFILE_OBJECT FileObj,PVOID CompRoutine,PVOID Contxt,ULONG Flags,PTDI_CONNECTION_INFORMATION RequestConnectionInfo,PTDI_CONNECTION_INFORMATION ReturnConnectionInfo);这个函数中最重要的三个参数是Irp、DevObj 和FileObj,第一个是预先分配好的一个IRP 结构体指针;第二个是这个IRP 将要转发到的设备对象,也就是TDI 传输器;第三个是TDI 传输器的文件对象指针,可以是代表传输地址的文件对象,可以是代表连接端点的文件对象,可以是代表控制信道的文件对象,不同的文件对象上可以进行的操作也不一样,比如TDI_LISTEN 操作只可以在代表连接端点的文件对象上进行。该函数主要是对新建的IRP 进行设置,关键是给这个IRP 设置了操作码为TDI_LISTEN. 在创建了这个IRP 以后,TDI 客户将这个IRP 请求转发到它的TDI 传输器,这个过程是通过调用IoCallDriver 函数来实现的。IoCallDriver 函数原型:NTSTATUSIoCallDriver(IN PDEVICE_OBJECT DeviceObject,IN OUT PIRP Irp);该函数将IRP 请求转发给指定的设备对象。在我们的程序中,既是将TDI 客户中生成的IRP 发给下层的TDI 传输器,即我们的协议驱动进行处理。DeviceObject 为代表下层TDI传输器的设备对象,IRP 为要进行的操作,如前面事例中生成的TDI_LISTEN 请求。在 TDI 客户调用IoCallDriver 之后,IRP 请求就转到了TDI 传输器,即我们的TCP/IP协议中处理了。4.3 TDI 传输器的实现TDI 传输器也就是我们的协议驱动,也就是TCP/IP 协议。简单的说,这层的主要操作仍然是根据上层TDI 客户提交过来的请求进行不同的处理。只不过这里又有特殊的含义,就是要完成TCP/IP 的相应功能,因此这一层是我们实现中最重要的部分。在这层中,TDI 传输器接收到上层TDI 客户转交过来的请求,系统根据用户注册的函数入口找到处理请求的函数irdcTCPInternalDeviceControlDispatch。该函数则根据操作的对象和操作的类型进行不同的函数调用。irdcTCPInternalDeviceControlDispatch 的函数原型:NTSTATUSirdcTCPInternalDeviceControlDispatch(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)参数DeviceObject 代表了当前的设备对象,也就是TDI 传输器。Irp 为IRP 请求指针,表明了要操作的文件对象和需要进行的操作。该函数首先根据不同的文件对象进行分类,然后对某一个文件对象可以进行的操作进行列表。当某一请求到来时,根据比较这些参数找到对应的操作。以下就按TCP/IP 协议对数据的处理流程详细进行分析。依数据传输的方向大致可以分成发送和接收过程。4.3.1 发送过程上层应用程序发起一个发送请求。首先应用程序调用CreateFile 函数打开TDI 客户,然后调用DeviceIoControl 将请求转发到内核的TDI 客户,TDI 客户进行相应的处理之后,调用TdibuildSend 设置一个 TDI_SEND 请求,然后再调用IoCallerDriver 将该请求转发给TDI传输器,即TCP/IP 协议进行处理。为了描述主线,这里暂把先前TCP 建立连接的三次握手过程给省略了。发送过程如图3 所示。图 3 发送框图数据从TDI 客户进入TDI 传输器后,经过一系列的函数调用,生成适合在网络上传输的数据包。这个过程包括对数据的封包,超时,创建重传队列,数据分片,路由设置等。发送数据时首先双方应该建立连接前完成一个三次握手的过程,在连接建立以后双方开始进行可靠的通信。图4 所示为建立连接以后,发送过程在TCP/IP 协议层中函数的调用流图。TDI 传输器的派遣例程调用tcp_send 函数发送数据,将数据转入到TCP 层,完成TCP 层的包头以及控制状态的设置。在调用ip_queue_xmit 后,数据转到IP 层进行处理,在这里完成IP 包格式的设置以及分片操作等。最后调用ether_output 函数设置好MAC 头以后,一个完整的数据帧就行成了,然而为了符合NDIS 对数据包格式的封装要求,这里需要对数据结构进行调整。数据在进入ether_output 函数前一直是以SK_BUFF的形式进行管理的,这个结构体有四个指针,通过对这四个指针的上下移动来对数据进行操作。在进入ether_output 函数之后数据重新打包成适合NDIS 接口传输的Packet 形式。然后调用NDIS 函数NdisSend函数将数据由下层驱动送出。图 4 发送过程TCP/IP 协议层函数流程图4.3.2 接收过程下层网卡接收到数据以后,将通知微端口驱动程序,微端口驱动程序再将数据指示给NDIS 协议驱动程序进行处理。在协议层中对数据进行一系列的处理之后再通知给TDI 客户,TDI 客户再将数据通知给上层应用程序。接收过程如图5 所示。图 5 接收框图数据从微端口指示给NDIS 协议驱动以后,首先将NDIS 层的数据包格式Packet 拆开组装成SK_BUFF 的形式,设置好该结构的各个成员。然后调整它的四个指针来获取不同层的实际数据。首先分离出MAC 帧头,判断收到的包是否为IP 包,否则直接丢弃,是则继续往上进入IP 层处理。然后分离出IP 头,判断当前包是否分片,是则等收齐所有分片以后重新组包往上传递,不是则直接上传。最后分离出TCP 头,通过分析TCP 头中所携带的信息,以及当前TCP 所在的状态来进行相应的处理。如当前的TCP 状态是尚未建立连接则调用tcp_rcv_state_process 函数,该函数根据TCP 头中标志位的置位情况来进行相应处理。如果已经建立连接则调用tcp_rcv_established 函数进行数据的接收过程处理,将接收的数据加入队列,当队列满了以后通过设置事件的信号态来指示上层的TDI 客户有数据到达,然后TDI客户以同样的方式通知上层应用程序。接收过程TCP/IP 协议层中的函数调用过程如下图6所示。图 6 接收过程TCP/IP 协议层函数流程图5. 结论 本文以RFC 文档中关于TCP/IP 协议的标准规范为理论基础,以Windows DDK 为开发工具,结合项目需求,设计开发了一套TCP/IP 协议。本套协议并未实现整个TCP/IP 协议族中的所有协议,只是对TCP 和IP 部分进行了实现。在前面总体协议框架的设计基础上,最终得到的产品有,FTP 测试应用程序,TDI 客户及TCP/IP 协议(TDI 传输器)。下面是测试该TCP/IP 协议的部分截图。图7 为启动加载TCP/IP 协议(irdcTCP)与TDI客户(TdiTirdcTcp)的截图。图8 为协议接收数据的截图。 图 7 启动TCP/IP 协议与TDI 客户截图 图8 接收数据截图 6. 详细设计代码 (1)映射网络驱动器功能实现; 实现代码如下:UpdateData(FALSE);DWORD nRetVal;NETRESOURCE nr;nr.dwType = RESOURCETYPE_ANY;LPTSTR Local =(LPTSTR)(LPCTSTR)m_strLocal;nr.lpLocalName=T2W(Local);LPTSTR Tar =(LPTSTR)(LPCTSTR)m_strTar;nr.lpRemoteName = T2W(Tar);nr.lpProvider = NULL;nRetVal = WNetAddConnection2(&nr, m_strPwd, m_strUser, FALSE);if(nRetVal = NO_ERROR)CString strText;strText.Format(CString(映射文件%s到网络驱动盘%s成功), m_strTar, m_strLocal);AfxMessageBox(strText);return;MessageBox(CString(映射网络驱动盘失败!);void CMapDlg:OnBnClickedButtonDismap()DWORD nRetVal;UpdateData(TRUE);nRetVal = WNetCancelConnection2(m_strLocal, CONNECT_UPDATE_PROFILE, FALSE);if(nRetVal = NO_ERROR)CString strText;strText.Format(CString(断开网络驱动器映射%s成功!),m_strLocal);MessageBox(strText);return;MessageBox(CString(断开网络驱动器映射失败!);(2)单个Ip共享资源搜索实现。(3)搜索所有计算机的共享资源实现。实现代码如下:void Ctmp1Dlg:OnBnClickedOk()m_ListCtrlres.DeleteAllItems();if(m_Operate=0)BYTE bIP4;m_IPtar.GetAddress(bIP0,bIP1,bIP2,bIP3);CString tarAdd;tarAdd.Format(CString(%d.%d.%d.%d),bIP0,bIP1,bIP2,bIP3);Search(tarAdd);else if(m_Operate=1)SearchAll();TCHAR* Ctmp1Dlg:CString2TCHAR(CString& str)int iLen = str.GetLength(); TCHAR* szRs = new TCHARiLen; lstrcpy(szRs, str.GetBuffer(iLen); str.ReleaseBuffer(); return szRs; void Ctmp1Dlg:OnBnClickedRadioAll()GetDlgItem(IDC_IPADDRESS_TAR)-EnableWindow(0);m_Operate=1;void Ctmp1Dlg:OnBnClickedRadioPer()GetDlgItem(IDC_IPADDRESS_TAR)-EnableWindow(1);m_Operate=0;int Ctmp1Dlg:Search(CString tarIP)TCHAR *tmp=CString2TCHAR(tarIP);PSHARE_INFO_1 BufPtr,p;NET_API_STATUS res;LPTSTR lpszServer = NULL;DWORD er=0,tr=0,resume=0, i;lpszServer = tmp;do / begin dores = NetShareEnum (lpszServer, 1, (LPBYTE *) &BufPtr, -1, &er, &tr, &resume);if(res = ERROR_SUCCESS | res = ERROR_MORE_DATA)p=BufPtr;for(i=0;ishi1_netname;CString strRemark=p-shi1_remark;DWORD dwType=p-shi1_type;CString strType;if(dwType=STYPE_DISKTREE)strType=CString(硬盘驱动);else if(dwType=STYPE_PRINTQ)strType=CString(打印机序列);else if(dwType=STYPE_DEVICE)strType=CString(通信设备);else if(dwType=STYPE_IPC)strType=CString(进程间通信(IPC);else if(dwType=STYPE_SPECIAL)strType=CString(特殊共享);else if(dwType=STYPE_TEMPORARY)strType=CString(临时共享)elsestrType.Format(CString(%d),dwType);int nCount=m_ListCtrlres.GetItemCount();m_ListCtrlres.InsertItem(nCount,tarIP,0);m_ListCtrlres.SetItemText(nCount,1,strNetName);m_ListCtrlres.SetItemText(nCount,2,strRemark);m_ListCtrlres.SetItemText(nCount,3,strType); p+;NetApiBufferFree(BufPtr);else if(res!=ERROR_SUCCESS&res!=ERROR_MORE_DATA&m_Operate=0)MessageBox(CString(没有共享信息!);while (res=ERROR_MORE_DATA); / end doreturn 0;void Ctmp1Dlg:SearchAll(void)LPSERVER_INFO_101 pBuf = NULL;LPSERVER_INFO_101 pTmpBuf;DWORD dwLevel = 101;DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH;DWORD dwEntriesRead = 0;DWORD dwTotalEntries = 0;DWORD dwServerType = SV_TYPE_SERVER; / all serversDWORD dwResumeHandle = 0;NET_API_STATUS nStatus;LPTSTR pszServerName = NULL;LPTSTR pszDomainName = NULL;DWORD i;WSADATA wsaData;WSAStartup(MAKEWORD(2,0), &wsaData);nStatus = NetServerEnum(pszServerName,dwLevel,(LPBYTE *) & pBuf,dwPrefMaxLen,&dwEntriesRead,&dwTotalEntries,dwServerType, pszDomainName, &dwResumeHandle);if (nStatus = NERR_Success) | (nStatus = ERROR_MORE_DATA) if (pTmpBuf = pBuf) != NULL) for (i = 0; i sv101_name;char szHostName128=0;int hostlength=HostName.GetLength();for(int j=0;jh_addr_list
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 安徽省合肥蜀山区七校联考2026届中考数学模试卷含解析
- 农业科技项目资金合作协议
- 2025年水性涂料生产环保型产品市场潜力及竞争策略研究报告
- 2025企业办公楼装修安全合同协议范本
- 2025年中国母猪养殖行业市场深度研究及投资战略咨询报告
- 2025年中国喷播机行业市场全景调研及投资规划建议报告
- 2025年中国蜗杆蜗轮减速机行业发展运行现状及投资潜力预测报告
- 2025年传统食品工业化生产智能化改造对行业竞争力的提升策略报告
- 2025年上海市房屋买卖合同样本
- 被动式超低能耗建筑2025年建筑节能与建筑节能技术应用与创新研究报告
- 2025四川绵阳科技城控股集团有限公司招聘28人(第一批)笔试历年参考题库附带答案详解
- 残疾人专职委员考试题目含答案
- 医疗器械网络销售质量管理规范宣贯培训课件2025年
- 高考英语3500个单词和短语
- (正式版)HGT 22820-2024 化工安全仪表系统工程设计规范
- 个人简历电子版
- 线性代数期末考试试题(含答案)
- 红色简约大方万人计划青年人才答辩PPT模板
- 湖北省武汉市各县区乡镇行政村村庄村名居民村民委员会明细及行政区划代码
- 办公室装修工程施工方案-
- 120 急 救转诊记录单
评论
0/150
提交评论