信息通信网络概论实验指导书_第1页
信息通信网络概论实验指导书_第2页
信息通信网络概论实验指导书_第3页
信息通信网络概论实验指导书_第4页
信息通信网络概论实验指导书_第5页
已阅读5页,还剩33页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

38/38信息通信网络概论实验指导书

目录实验一TCP/IP协议与Socket编程认识实验 4一、 实验目的 4二、 实验内容 4三、 实验原理 4四、 实验步骤 5五、 思考题或讨论题 6实验二FTP客户端通信程序设计 7一、 实验目的 7二、 实验内容 7三、 实验原理 7四、 思考题或讨论题 9实验三基于客户/服务器模式的网络通信编程实现 11一、 实验目的 11二、 实验内容 11三、 实验原理 11四、 应用程序的设计方法和步骤 12五、 聊天室应用程序设计的具体说明 141、聊天室的工作流程 142、套接字事件处理 153、系统实现 163.1利用MFCAppWizard生成程序框架 163.2增加控件对象 163.3从CAsyncSocket类继承 163.4建立客户机与服务器之间的连接 163.5发送和接收数据 173.6终止连接 174、结束语 17六、 思考题或讨论题 18实验四﹑计算机网络通信应用程序设计 19(一)基于TCP/IP的计算机网络通信应用程序设计 19一、 实验目的 19二、 实验内容 19三、 实验步骤 19(二)基于UDP/IP的计算机网络通信应用程序设计 20一、 实验目的 20二、 实验内容 20三、 实验步骤 21四、 思考题或讨论题 21附录:实验中需要用到的WINSOCKAPI函数和数据结构 22accept(): 22bind() 23closesocket(): 24connect(): 26listen(): 27socket(): 28recv(): 29send(): 31WSAAsyncSelect(): 32WSAStartup(): 36Gethostbyname 37Gethostbyaddr 38inet_ntoa 38inet_addr 38WSADATA和LPWSADATA 38

实验一TCP/IP协议与Socket编程认识实验实验目的熟悉TCP/IP协议的功能和网络操作;了解基于SOCKET的编程原理;编写一个小型的Socket实用程序,初步了解Windows环境下使用Socket的编程。实验内容在已有的程序框架下,编写一个查询主机地址和域名的程序。实现功能:输入域名查询IP地址;输入IP地址查询域名。实验原理什么是WindowsSockets规范?WindowsSockets规范以U.C.Berkeley大学BSDUNIX中流行的Socket接口为范例定义了一套MicosoftWindows下网络编程接口。它不仅包含了人们所熟悉的BerkeleySocket风格的库函数;也包含了一组针对Windows的扩展库函数,以使程序员能充分地利用Windows消息驱动机制进行编程。WindowsSockets规范本意在于提供给应用程序开发者一套简单的API,并让各家网络软件供应商共同遵守。此外,在一个特定版本Windows的基础上,WindowsSockets也定义了一个二进制接口(ABI),以此来保证应用WindowsSocketsAPI的应用程序能够在任何网络软件供应商的符合WindowsSockets协议的实现上工作。因此这份规范定义了应用程序开发者能够使用,并且网络软件供应商能够实现的一套库函数调用和相关语义。遵守这套WindowsSockets规范的网络软件,我们称之为WindowsSockets兼容的,而WindowsSockets兼容实现的提供者,我们称之为WindowsSockets提供者。一个网络软件供应商必须百分之百地实现WindowsSockets规范才能做到现WindowsSockets兼容。任何能够与WindowsSockets兼容实现协同工作的应用程序就被认为是具有WindowsSockets接口。我们称这种应用程序为WindowsSockets应用程序。WindowsSockets规范定义并记录了如何使用API与Internet协议族(IPS,通常我们指的是TCP/IP)连接,尤其要指出的是所有的WindowsSockets实现都支持流套接口和数据报套接口.应用程序调用WindowsSockets的API实现相互之间的通讯。WindowsSockets又利用下层的网络通讯协议功能和操作系统调用实现实际的通讯工作。它们之间的关系如图1-1。Winsock编程模型建立socket。程序使用socket进行网络时,必须先建立一个socket。为了建立一个socket,成需要调用socket函数。例子:socket_handle=socket(protocol_family,_socket_type,protocol);配置一个socket。为了配置一个,程序可使用WinsockAPI中不同的函数。一般来讲,每个socket需要五种信息:本地和远地机的IP地址,本地和远地进程的协议端口,联接上使用的协议。连接一个socket。面向连接客户程序必须提供给Socket的唯一地址信息是远地主机信息—IP地址和协议端口。使用一个Socket,程序能够使用WinsockAPI在一个配置好的Socket上传送和接收数据。I/O函数如下:Send,通过连接的Socket传送数据,使用特殊的标志控制Socket的行为。Sendto,将数据传送给Socket地址结构指定的主机,传送时使用一个简单的报文缓冲区。Recvfrom,从Socket接收数据,选择发送主机的网络地址,传送时使用一个简单的报文缓冲区。使用一个连接的Socket。由于Send函数不能指定目的地址,因此,程序只能在连接的Socket上使用它。也就是说,在程序使用Send函数之前,必须建立一个Socket。使用一个无连接的Socket。当没有建立Socket连接时,上述的Send函数便不能使用,这是需要用Sendto函数。实验步骤网络程序初始化,服务器和客户端WinSockAPI均要求在调用其他WinSock函数以前先调用WSAStartUp函数初始化。创建套接字Socket()。配置并启动套接字。通过Socket发送和接收数据。程序结束时必须关闭Socket,使用与WSAStartUp()相对应的函数WSACleanUp(),释放所分配的内部缓冲区和其他资源。思考题或讨论题1.WinInet有什么作用?2.结合本次实验,谈谈使用MFCWinInet类有哪些优点?

实验二FTP客户端通信程序设计实验目的了解Windows下的TCP/IP通信方式与网络操作熟悉FTP的编程的过程;学会用可视化编程语言编写调试简单的通信程序。实验内容在已有的程序框架下,编写一个FTP客户端程序。实现功能:连接到FTP主机,下载FTP文件服务器文件列表;切换访问目录;向FTP服务器发送文件(上传文件);从FTP服务器下载文件(下载文件)。实验原理在使用MFC编程时,要连接到FTP服务器是一件非常简单的事情,只需要两个简单的步骤,首先必须建立一个CinternetSession对象,用类CinternetSession创建并初始化一个或几个同时存在的Internet会话(Session),并描述与代理服务器的连接(如果有必要的话),如果在程序运行期间需要保持与Internet的廉洁,可以创建一个CinternetSession对象作为类CwinApp的成员。MFC中的类C管理我们与Internet服务器的连接,并直接操作服务器上的目录和文件,的WinInet支持的三个Internet功能之一,我们需要先创建一个CinternetSession实例和一个C对象就可以实现和一个FTP服务器通信,我们不需要直接创建C对象,而是通过调用CinternetSession::Get来完成这项工作。他创建C对象并返回一个指向该对象的指针。在FTP连接的程序中,主要适用下列7个函数:CInternetSession对象语法:CInternetSession(LPCTSTRpstrAgent,DWORDdwConText,DWORDdwAccessType,LPCTSTRpstrProxyName,LPCTSTRpstrProxyBypass,DWORDdwFlags);注释:在创建CInternetSession对象时调用这个成员函数,CInternetSession是应用程序第一个要调用的Internet函数,它将创始化内部数据结构,以备将来在应用程序中调用。如果dwFlags包含INTERNET_FLAG_ASYNC,那末从这个句柄派生的所有的句柄,在状态回调例程注冊之前,都会出现异步状态。如果沒有打开Internet连接,CInternetSession就会抛出一个例外,fxThorowInternetException。Get()函数。语法:C*CIternetSession::Get(LPCTSTRpstrServer,LPCTSTRpstrUserName,LPCTSTRpstrPassword,INTERNET_PORTnPort,BOOLbPassive);注释:调用这个函数建立一个FTP连接,并获得一个指向C对象的指针,Get连接到一个FTP服务器,创建并返回指向C对象的指针,它不在服务器上进行任何操作。如果打算读写文件,必须进行分步操作。关于查找,打开和读/写文件的信息需参考C和C类。对这个函数的调用返回一个指向C对象的指针。如果调用失败,检查抛出的CInternetException对象,就可以确定失败的原因。GetFile()函数。语法:BOOLGetpstrRemotepstrLocalbFailExists,DWORDdwAttributes,DWORDdwFlags,DWORDdwContext);注释:调用这个成员函数,可以从FTP服务器取得文件,并且把文件保存在本地机器上。GetFile()函数是一个比较高级的例程,它可以处理所有有关从FTP服务器读文件,以及把文件存放在本地机器上的工作。如果dwFlags为,文件数据的传输也会把控制和格式符转化为Windows中的等阶符号。默认的传输模式是二进制模式,文件会以和服务器上相同的格式被下载。pstrRemoteFile和pstrLocalFile可以是相对于当前目录的部分文件名,也可以是全文件名,在这两个名字中间,都既可以用反斜杠(\)或者正斜杠(/)来作为文件名的目录分隔符,GetFile()在使用前会把目录分隔符转化为适当的字符。可以用自己选择的值来取代dwContext默认的值,设置为上下文标识符与C对象的定位操作有关,这个操作由C中的CInternetSession对象创建。返回给CInternetSession::OnStatusCallBack的值指出了所标识操作的状态。如果调用成功,函数的返回为非0,否则返回0,如果调用失败,可以调用Win32函数GetLastError(),确认出错的原因。PutFile()函数。语法:BOOLPutpstrLocalFile,LPCTSTRpstrRemovedwFlags,DWORDdwContext);注释:调用这个成员函数可以把文件保存到FTP服务器。PutFile()函数是一个比较高级的例程,它可以处理有关把文件存放到服务器上的工作。只发送数据,或要严格控制文件传输的应用程序,应该调用OpenFile和CInternet::Write。利用自己选择的值来取代dwContext默认的值,设置为上下文标识符,上下文标识符是CInternetSession对象创建的C对象的特定操作有关,这个值返回给CInternetSession::OnStateCallBack,从而把操作的状态通报给它所标识的上下文。如果调用成功,函数的返回为非0,否则返回0,如果调用失败,可以调用Win32函数GetLastError(),确认出错的原因。FTP文件查找函数。调用这个成员函数构造一个C对象。FindFile()函数。调用这个函数查找FTP文件,调用它检索到第一个FTP文件后,可以调用FindNextFile()检索后面的FTP文件。FindNextFile()函数。调用这个函数继续查找文件,在调用任何属性以前,必须已经至少调用过一次此函数。以上函数的具体使用方法可以参见MSDN。思考题或讨论题1.WinInet有什么作用?2.结合本次实验,谈谈使用MFCWinInet类有哪些优点?

实验三基于客户/服务器模式的网络通信编程实现(基于Socket的网络聊天室的设计与实现)实验目的进一步了解网络编程的过程;掌握Windows环境下基于WinSock的编程方法和通信实现;熟悉客户/服务器模式的网络通信编程实现,编写一个聊天工具,即以客户端和服务器端的模式进行互发消息。实验内容Internet上可以提供一种叫IRC的服务。使用者通过客户端的程序登录到IRC服务器上,就可以与登录在同一IRC服务器上的客户进行交谈,这也就是平常所说的聊天室。在已有的程序框架下,编写一个类似的聊天程序。实现功能:服务器端:建立Socket,绑定端口,并监听;接受客户端的连接;与客户端进行通讯;断开连接。客户端:建立Socket,并申请连接到服务器;与服务器进行通讯;断开连接。实验原理一个在建立分布式应用时最常用的范例便是客户机/服务器模型。在这种方案中客户应用程序向服务器程序请求服务。这种方式隐含了在建立客户机/服务器间通讯时的非对称性。客户机/服务器模型工作时要求有一套为客户机和服务器所共识的惯例来保证服务能够被提供(或被接受)。这一套惯例包含了一套协议。它必须在通讯的两头都被实现。根据不同的实际情况,协议可能是对称的或是非对称的。在对称的协议中,每一方都有可能扮演主从角色;在非对称协议中,一方被不可改变地认为是主机,而另一方则是从机。一个对称协议的例子是Internet中用于终端仿真的TELNET。而非对称协议的例子是Internet中的FTP。无论具体的协议是对称的或是非对称的,当服务被提供时必然存在“客户进程”和“服务进程”。一个服务程序通常在一个众所周知的地址监听对服务的请求,也就是说,服务进程一直处于休眠状态,直到一个客户对这个服务的地址提出了连接请求。在这个时刻,服务程序被“惊醒”并且为客户提供服务-对客户的请求作出适当的反应。这一请求/相应的过程可以简单的用图2-1表示。虽然基于连接的服务是设计客户机/服务器应用程序时的标准,但有些服务也是可以通过数据报套接口提供的。应用程序的设计方法和步骤服务端建立Socket初始化WinSock的动态连接库后,需要在服务器端建立一个监听的Socket,为此可以调用Socket()函数用来建立这个监听的Socket,并定义此Socket所使用的通信协议。此函数调用成功返回Socket对象,失败则返回INVALID_SOCKET(调用WSAGetLastError()可得知原因,所有WinSocket的函数都可以使用这个函数来获取失败的原因)。绑定端口接下来要为服务器端定义的这个监听的Socket指定一个地址及端口(Port),这样客户端才知道待会要连接哪一个地址的哪个端口,为此我们要调用bind()函数,该函数调用成功返回0,否则返回SOCKET_ERROR。监听当服务器端的Socket对象绑定完成之后,服务器端必须建立一个监听的队列来接收客户端的连接请求。listen()函数使服务器端的Socket进入监听状态,并设定可以建立的最大连接数(目前最大值限制为5,最小值为1)。该函数调用成功返回0,否则返回SOCKET_ERROR。服务器端的Socket调用完listen()后,如果此时客户端调用connect()函数提出连接申请的话,Server端必须再调用accept()函数,这样服务器端和客户端才算正式完成通信程序的连接动作。为了知道什么时候客户端提出连接要求,从而服务器端的Socket在恰当的时候调用accept()函数完成连接的建立,我们就要使用WSAAsyncSelect()函数,让系统主动来通知我们有客户端提出连接请求了。该函数调用成功返回0,否则返回SOCKET_ERROR。服务器端接受客户端的连接请求当Client提出连接请求时,Server端hwnd视窗会收到WinsockStack送来我们自定义的一个消息,这时,我们可以分析lParam,然后调用相关的函数来处理此事件。为了使服务器端接受客户端的连接请求,就要使用accept()函数,该函数新建一Socket与客户端的Socket相通,原先监听之Socket继续进入监听状态,等待他人的连接要求。该函数调用成功返回一个新产生的Socket对象,否则返回INVALID_SOCKET。结束socket连接结束服务器和客户端的通信连接是很简单的,这一过程可以由服务器或客户机的任一端启动,只要调用closesocket()就可以了,而要关闭Server端监听状态的socket,同样也是利用此函数。客户端客户端比较简单,只有一个socket,与服务端进行连接。连接建立好后,通过此SOCKET发送和接收信息。建立客户端的Socket客户端应用程序首先也是调用WSAStartup()函数来与Winsock的动态连接库建立关系,然后同样调用socket()来建立一个TCP或UDPsocket(相同协定的sockets才能相通,TCP对TCP,UDP对UDP)。与服务器端的socket不同的是,客户端的socket可以调用bind()函数,由自己来指定IP地址及port号码;但是也可以不调用bind(),而由Winsock来自动设定IP地址及port号码。提出连接申请客户端的Socket使用connect()函数来提出与服务器端的Socket建立连接的申请,函数调用成功返回0,否则返回SOCKET_ERROR。数据的传送虽然基于TCP/IP连接协议(流套接字)的服务是设计客户机/服务器应用程序时的主流标准,但有些服务也是可以通过无连接协议(数据报套接字)提供的。介绍一下TCPsocket与UDPsocket在传送数据时的特性:Stream(TCP)Socket提供双向、可靠、有次序、不重复的资料传送。Datagram(UDP)Socket虽然提供双向的通信,但没有可靠、有次序、不重复的保证,所以UDP传送数据可能会收到无次序、重复的资料,甚至资料在传输过程中出现遗漏。由于UDPSocket在传送资料时,并不保证资料能完整地送达对方,所以绝大多数应用程序都是采用TCP处理Socket,以保证资料的正确性。一般情况下TCPSocket的数据发送和接收是调用send()及recv()这两个函数来达成,而UDPSocket则是用sendto()及recvfrom()这两个函数,这两个函数调用成功发挥发送或接收的资料的长度,否则返回SOCKET_ERROR。聊天室应用程序设计的具体说明1、聊天室的工作流程Socket()Socket()Bind()Listen()服务器侦听套接字Connect()Accept()Closesocket()Send()Recv()创建连接套接字客户机连接套接字Socket()Bind()Recv()Send()Closesocket()Closesocket()首先,服务器要创建一个用于侦听的套接字,为该套接字分配地址之后,调用listen()函数使它处于侦听状态;客户机在创建套接字完毕后,为套接字分配地址,然后调用connect()函数,请求与服务器套接字连接;服务器套接字在收到客户机的连接请示后,调用accept()函数,该函数创建一个用于连接的套接字。应用该套接字和客户机上的连接套接字,用户就可以在服务器和客户机之间进行数据传输了。在结束传输之后,客户机调用closesocket()函数关闭套接字,服务器也调用该函数关闭用于侦听和连接的套接字。2、套接字事件处理消息处理函数,这些函数并不对套接字作实质上的操作,是Windows为套接字加上消息驱动的产物。它们和特定的套接字消息相关联,当消息到来时,应用程序框架就调用这些函数。它们都是CAsyncSocket类的虚函数,因为MFC库中没有定义这些函数的内容,程序员必须根据需要重载这些函数,把对套接字进行实质操作的函数加进这些函数中。OnAccept():监听套接字在断口听到连接请求时,应用程序框架调用该函数以告之可以接受或拒绝连接请求,调用Accept来接受请求,建立连接。OnConnect():当客户端套接字连接请求完成后,应用程序框架调用该函数,告之是否成功。OnSend():框架调用该函数通知该套接字现在可以调用Send函数开始传送数据。OnReceive():框架调用该函数通知套接字可以调用Receive函数从数据缓冲区中取数据。OnClose():框架调用该函数告之与其相连的对方套接字已被关闭。3、系统实现3.1利用MFCAppWizard生成程序框架在VisualC++的IDE环境下选择菜单File—New—Projects—MFCAppWizard(exe)—ProjectName—“OK”—“NEXT”—WindowsSockets—“Finish”按钮,选择“OK”按钮,应用程序的框架就将自动创建。3.2增加控件对象在创建了应用程序框架之后,可以布置程序的主对话框,向应用程序的主对话框添加控件。设计好了对话框之后,选取View菜单中的ClassWizard菜单项,或直接按“Ctrl+W”,打开MFCClassWizard,将对话框中的控件和变量相关联,其关系如下表所示。变量说明表对象名称类别类别IDC_BTN_CONNECTm_btnConnectControlCButtonIDC_COMBO_TYPEm_cmbTypeControlCComboBoxIDC_EDIT_MSGm_strMsgValueCStringIDC_EDIT_SERVNAMEm_strServNameValueCStringIDC_EDIT_SERVPORTm_nSerPortValueIntIDC_LIST_RECEIVEDm_listReceivedControlCListBoxIDC_LIST_SENTm_listSentControlCListBox3.3从CAsyncSocket类继承选择Insert菜单中的NewClass——选取Classtype为GenericClass——在Baseclass的DerivedFrom列中输入CAsyncSocket,——在As列中接受默认值public,点击”OK”按钮,就可以把这个新创建的类添加到应用程序中。向该套接字类中添加一个成员变量,用作指向父对话框窗口的指针,指针变量的类型为CTalkDlg*(Cdialog的派生类),变量名为m_pDlg,访问权限为私有。最后,添加套接字类事件处理函数,这些函数将用于调用对话框中名称类似的那些函数。3.4建立客户机与服务器之间的连接为了完成连接,需要添加对套接字事件的处理函数,在对话框类中添加OnAccept()事件处理函数和OnConnect()事件处理函数。如果现在可以编译和运行应用程序,就可以启动两个副本,把其中一个设置为侦听模式,然后把另一个应用程序与之相连接。为此,先向对话框类()添加三个成员函数,这三个函数是套接字类()的事件处理函数需要调用的。把三个函数的类型都指定为void,访问权限为公共。指定第一个函数声明为OnSend(),第二个函数的声明为OnReceive,第三函数的声明为OnClose。3.5发送和接收数据如果两个应用程序间建立了连接,用户就能够在对话框窗口中的编辑框中输入文本消息,然后单击“发送”按钮,就应该可以把消息发送到另一个应用程序,一旦消息发送出去了,它将被添加到已发送消息的列表框中。当“发送”按钮被单击之后,应用程序需要检查是否有消息输入了编辑框,获取该消息的长度,并发送该消息,然后把此消息添加到列表框中。为了在应用程序中添加此项功能,使用ClassWizard向“发送”按钮(ID:IDOK)的单击事件(BN—CLICKED)添加一个事件处理函数,注意不要接受默认的函数名,将函数名改成OnSendMsg(),编辑该函数。对于消息的接收方,当套接字的OnReceive事件被触发时,表明一个消息已经到达了,可以用Receive()函数从套接字检索到该消息。如果消息被顺利检索到,需要把接收的字符数组转换成Cstring类型,并把接收的消息添加到已接收的消息的列表框中。通过编辑对话框类(CtalkDlg)的OnReceive()函数。3.6终止连接结束消息传送之后应该终止两个应用程序之间的连接,这个终止连接的操作是由客户机应用程序的用户通过单击“断开”按钮来实现的。然后应用程序会接收到一个OnClose套接字事件。和建立连接的过程相反,连接的套接字需要断开,发送消息的控件需要置为禁用状态。在客户端,“连接”按钮控件由禁用状态变成可用,因为应用程序允许客户机程序改变某些参数,并打开与另一个服务器程序的连接。同时,服务器应用程序继续侦听是否有其他的连接请求,侦听的端口等信息不变。4、结束语这个应用程序在MFCWinSock编程中很有代表性,可以用于两台计算机之间进行字符串传输;创建思路简单,就是利用MFCAppWizard生成程序框架,通过对CAsynSocket类增加一个指向对话框类得指针,对CAsynSocket类中的一些事件处理函数进行重载,使这些套接字事件发生时,应用程序能够自动到对话框类中寻找合适的函数执行。这个聊天室应用程序是基于客户/服务器模型的,一个服务器只能支持一个客户,因此它实际上是一个基于“点对点”模型的应用程序。通过这个应用程序,用户可以在两台计算机之间进行字符串传输——即可以为两个人进行网上聊天提供服务,而且两个人的传输的字符串被保留在程序的列表框中,并且进行分类,分为传送和接收的字符串。思考题或讨论题1.本次实验所涉及的“实体”是什么?实体间通过什么方式建立协议?2.服务和协议的区别与联系?本次实验的协议过程(即客户-服务器方式)是怎样建立的?有哪些服务?3、本次实验的协议提供了什么服务?试想,用此协议还可以提供怎样的服务?这种服务在自动化学科领域的意义是什么?实验四﹑计算机网络通信应用程序设计(一)基于TCP/IP的计算机网络通信应用程序设计实验目的1.通过本实验课程的学习,使学生能够理解TCP协议通信的基本原理。2.通过运用WinSock接口编写网络通信应用程序,掌握TCP网络应用程序架构的设计思想。3.学会设计利用TCP简单的应用层协议。实验内容在Windows网络环境下,以其中的2台计算机为对象,构成主从计算机应用系统,设计简单的应用层协议,开发基于TCP/IP的网络通信程序,实现数据传送等。基于TCP的计算机网络通信程序,实现了两人点对点聊天的功能,同时,还添加了一定的网络应用层自定义协议,例如:在聊天过程中输入/n会在聊天对话框内画一个牛;输入/p会在聊天对话框内画一个电话;在聊天过程中输入/r会打开一个windows资源管理器,并打开指定的路径;输入/l会弹出一个对话框……;(实现以上功能的函数是DoAction,用的到的头文件是有textprotcol.h)实验步骤服务器端1:创建套接字并将套接字绑定到一个本地地址和端口上(create)。2:将套接字设为监听模式,准备接受客户请求(listen)。3:等待客户请求到来;请求到来后,接受请求,返回一个新的对应于此次连接的套接字(accept)。4:用返回的套接字和客户端进行通信(send/receive)。5:返回,等待另一客户请求。6:关闭套接字。客户端1:创建套接字(create)。2:向服务器发出连接请求(connect)。3:和服务器进行通信(send/receive)。4:关闭套接字。(二)基于UDP/IP的计算机网络通信应用程序设计实验目的1.通过本实验课程的学习,使学生能够理解UDP协议通信的基本原理。2.通过运用WinSock接口编写网络通信应用程序,掌握UDP网络应用程序架构的设计思想。3.学会设计利用UDP简单的应用层协议。实验内容在Windows网络环境下,以其中的2台计算机为对象,构成主从计算机应用系统,设计简单的应用层协议,开发基于UDP/IP的网络通信程序,实现数据传送等。基于UDP的计算机网络通信程序,实现了多人的点对点聊天功能,同时,还添加了一定的网络应用层自定义协议,例如:在聊天过程中输入/n会在聊天对话框内画一个牛;输入/p会在聊天对话框内画一个电话;在聊天中输入/z会在聊天对话框内画一个猪的图案;在聊天过程中输入/r会打开一个windows资源管理器,并打开指定的路径……(实现以上功能的函数是DoAction,用的到的头文件是有textprotcol.h)本程序中的传输层协议使用的是UDP/IP协议,建立连接的过程和前面实验类似。但是,UDP协议的在建立连接中不需要先监听(listen)网络,建立连接(connect,accept)等过程,只需要绑定指定的端口。(具体通信过程请参看PPT讲义)另外,在该程序实现的过程中使用了多线程。实验步骤服务器端1.创建套接字并将套接字绑定到一个本地地址和端口上(create)。2.等待接收数据(ReceiveFrom)。3.关闭套接字。客户端1.创建套接字(create)。2.向服务器发送数据(sendto)。3.关闭套接字。思考题或讨论题1、结合所学知识与实验中的感受,说明TCP协议和UDP协议各自的优缺点。在工业控制的现场中,要通过网络控制一台焊接机器人的运行,要求控制数据能正确传输。试分析说明,采用哪种运输层协议比较好?另外,网络中使用的IP电话服务采用的是哪种运输层协议?为什么要采用这种协议?并说明理由。2、思考和调研目前常用的通信工具之一:QQ的基本实现方式。考虑其各种不同的应用可能采取的是TCP和UDP中的哪种协议。如果需要对本实验结果进行进一步改进,有哪些想法。

附录:实验中需要用到的WINSOCKAPI函数和数据结构需要包含头文件#include<winsock.h>accept():在一个套接口接受一个连接。语法:SOCKETPASCALFARaccept(SOCKETs,structsockaddrFAR*addr,intFAR*addrlen);参数:s:套接口描述字,该套接口在listen()后监听连接。addr:(可选)指针,指向一缓冲区,其中接收为通讯层所知的连接实体的地址。Addr参数的实际格式由套接口创建时所产生的地址族确定。addrlen:(可选)指针,指向存有addr地址长度的整形数。注释:本函数从s的等待连接队列中抽取第一个连接,创建一个与s同类的新的套接口并返回句柄。如果队列中无等待连接,且套接口为非阻塞方式,则accept()阻塞调用进程直至新的连接出现。如果套接口为非阻塞方式且队列中等待连接,则accept()返回一错误代码。已接受连接的套接口不能用于接受新的连接,原套接口仍保持开放。addr参数为一个返回参数,其中填写的是为通讯层所知的连接实体地址。addr参数的实际格式由通讯时产生的地址族确定。addrlen参数也是一个返回参数,在调用时初始化为addr所指的地址空间;在调用结束时它包含了实际返回的地址的长度(用字节数表示)。该函数与SOCK_STREAM类型的面向连接的套接口一起使用。如果addr与addrlen中有一个为零NULL,将不返回所接受的套接口远程地址的任何信息。返回值:如果没有错误产生,则accept()返回一个描述所接受包的SOCKET类型的值。否则的话,返回INVALID_SOCKET错误,应用程序可通过调用WSAGetLastError()来获得特定的错误代码。addrlen所指的整形数初始时包含addr所指地址空间的大小,在返回时它包含实际返回地址的字节长度。错误代码:WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。WSAEFAULT:addrlen参数太小(小于socket结构的大小)。WSAEINTR:通过一个WSACancelBlockingCall()来取消一个(阻塞的)调用。WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。WSAEINVAL:在accept()前未激活listen()。WSAEMFILE:调用accept()时队列为空,无可用的描述字。WSAENOBUFS:无可用缓冲区空间。WSAENOTSOCK:描述字不是一个套接口。WSAEOPNOTSUPP:该套接口类型不支持面向连接服务。WSAEWOULDBLOCK:该套接口为非阻塞方式且无连接可供接受。bind()将一本地地址与一套接口捆绑。语法:intPASCALFARbind(SOCKETs,conststructsockaddrFAR*name,intnamelen);参数:s:标识一未捆绑套接口的描述字。name:赋予套接口的地址。sockaddr结构定义如下:structsockaddr{u_shortsa_family;charsa_data[14];};namelen:name名字的长度。注释:本函数适用于未连接的数据报或流类套接口,在connect()或listen()调用前使用。当用socket()创建套接口后,它便存在于一个名字空间(地址族)中,但并未赋名。bind()函数通过给一个未命名套接口分配一个本地名字来为套接口建立本地捆绑(主机地址/断口号)。在Internet地址族中,一个名字包括几个组成部分,对于SOCK_PGRAM和SOCK_STREAM类套接口,名字由三部分组成:主机地址,协议号(显式设置为UDP和TCP)和用以区分应用的端口号。如果一个应用并不关心分配给它的地址,则可将Internet地址设置为INADDR_ANY,或将端口号置为0。如果Internet地址段为INADDR_ANY,则可使用任意网络接口;在有多种主机环境下可简化编程。如果端口号置为0,则WINDOWS套接口实现将给应用程序分配一个值在1024到5000之间的唯一的端口。应用程序可在bind()后用getsockname()来获知所分配的地址,但必需注意的是,getsockname()只有在套接口连接成功后才会填写Internet地址,这是由于在多种主机环境下若干种Internet地址都是有效的。返回值:如无错误发生,则bind()返回0。否则的话,将返回SOCKET_ERROR,应用程序可通过WSAGetLastError()获取相应错误代码。错误代码:WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。WSAEADDRINUSE:所定端口已在使用中(参见setoption()中的SO_REUSEADDR选项)。WSAEFAULT:namelen参数太小(小于sockaddr结构的大小)。WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。WSAEAFNOSUPPORT:本协议不支持所指定的地址族。WSAEINVAL:该套接口已与一个地址捆绑。WSAENOBUFS:无足够可用缓冲区,连接过多。WSAENOTSOCK:描述字不是一个套接口。closesocket():关闭一个套接口。语法:intPASCALFARclosesocket(SOCKETs);参数:s:一个套接口的描述字。注释:本函数关闭一个套接口。更确切地说,它释放套接口描述字s,以后对s的访问均以WSAENOTSOCK错误返回。若本次为对套接口的最后一次访问,则相应的名字信息及数据队列都将被释放。closesocket()的语义受SO_LINGER与SO_DONTLINGER选项影响,对比如下:选项间隔关闭方式等待关闭与否SO_DONTLINGER不关心优雅否SO_LINGER零强制否SO_LINGER非零优雅是若设置了SO_LINGER,并设置了零超时间隔,则closesocket()不被阻塞立即执行,不论是否有排队数据未发送或未被确认。这种关闭方式称为“强制”或“失效”关闭,因为套接口的虚电路立即被复位,且丢失了未发送的数据。在远端的recv()调用将以WSAECONNRESET出错。若设置了SO_LINGER并确定了非零的超时间隔,则closesocket()调用阻塞进程,直到所剩数据发送完毕或超时。这种关闭称为“优雅的”关闭。请注意如果套接口置为非阻塞且SO_LINGER设为非零超时,则closesocket()调用将以WSAEWOULDBLOCK错误返回。若在一个流类套接口上设置了SO_DONTLINGER,则closesocket()调用立即返回。但是,如果可能,排队的数据将在套接口关闭前发送。请注意,在这种情况下WINDOWS套接口实现将在一段不确定的时间内保留套接口以及其他资源,这对于想用所以套接口的应用程序来说有一定影响。返回值:如无错误发生,则closesocket()返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。错误代码:WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。WSAENOTSOCK:描述字不是一个套接口。WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。WSAEINTR:通过一个WSACancelBlockingCall()来取消一个(阻塞的)调用。WSAEWOULDBLOCK:该套接口设置为非阻塞方式且SO_LINGER设置为非零超时间隔。connect():建立与一个端的连接。语法:intPASCALFARconnect(SOCKETs,conststructsockaddrFAR*name,intnamelen);参数:s:标识一个未连接套接口的描述字。name:欲进行连接的端口名。namelen:名字长度。注释:本函数用于创建与指定外部端口的连接。s参数指定一个未连接的数据报或流类套接口。如套接口未被捆绑,则系统赋给本地关联一个唯一的值,且设置套接口为已捆绑。请注意若名字结构中的地址域为全零的话,则connect()将返回WSAEADDRNOTAVAIL错误。对于流类套接口(SOCK_STREAM类型),利用名字来与一个远程主机建立连接,一旦套接口调用成功返回,它就能收发数据了。对于数据报类套接口(SOCK_DGRAM类型),则设置成一个缺省的目的地址,并用它来进行后续的send()与recv()调用。返回值:若无错误发生,则connect()返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。对阻塞套接口而言,若返回值为SOCKET_ERROR则应用程序调用WSAGetLsatError()。如果它指出错误代码为WSAEWOULDBLOCK,则您的应用程序可以:1.用select(),通过检查套接口是否可写,来确定连接请求是否完成。或者,2.如果您的应用程序使用基于消息的WSAAsynSelect()来表示对连接事件的兴趣,则当连接操作完成后,您会收到一个FD_CONNECT消息。错误代码:WSAENOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。WSAEADDRINUSE:所指的地址已在使用中。WSAEINTR:通过一个WSACancelBlockingCall()来取消一个(阻塞的)调用。WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。WSAEADDRNOTAVAIL:在本地机器上找不到所指的地址。WSAENOTSUPPORT:所指族中地址无法与本套接口一起使用。WSAECONNREFUSED:连接尝试被强制拒绝。WSAEDESTADDREQ:需要目的地址。WSAEFAULT:namelen参数不正确。WSAEINVAL:套接口没有准备好与一地址捆绑。WSAEISCONN:套接口早已连接。WSAEMFILE:无多余文件描述字。WSAENETUNREACH:当前无法从本主机访问网络。WSAENOBUFS:无可用缓冲区。套接口未被连接。WSAENOTSOCK:描述字不是一个套接口。WSAETIMEOUT:超时时间到。listen():创建一个套接口并监听申请的连接.语法:intPASCALFARlisten(SOCKETs,intbacklog);参数:S:用于标识一个已捆绑未连接套接口的描述字。backlog:等待连接队列的最大长度。注释:为了接受连接,先用socket()创建一个套接口,然后用listen()为申请进入的连接建立一个后备日志,然后便可用accept()接受连接了。listen()仅适用于支持连接的套接口,如SOCK_STREAM类型的。套接口s处于一种“变动”模式,申请进入的连接请求被确认,并排队等待被接受。这个函数特别适用于同时有多个连接请求的服务器;如果当一个连接请求到来时,队列已满,那么客户将收到一个WSAECONNREFUSED错误。当没有可用的描述字时,listen()函数仍试图正常地工作。它仍接受请求直至队列变空。当有可用描述字时,后续的一次listen()或accept()调用会将队列按照当前或最近的“后备日志”重新填充,如有可能的话,将恢复监听申请进入的连接请求。返回值:如无错误发生,listen()返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。错误代码:WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。WSAEADDRINUSE:试图用listen()去监听一个正在使用中的地址。WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。WSAEINVAL:该套接口未用bind()进行捆绑,或已被连接。WSAEISCONN:套接口已被连接。WSAEMFILE:无可用文件描述字。WSAENOBUFS:无可用缓冲区空间。WSAENOTSOCK:描述字不是一个套接口。WSAEOPNOTSUPP:该套接口不正常listen()调用。socket():建立Socket,此函数用来建立一个Socket描述字,并为此Socket建立其所使用的资源。语法:SOCKETPASCALFARsocket(intaf,inttype,intprotocol)参数:af:目前只提供PF_INET(AF_INET);type:Socket的类型(SOCK_STREAM、SOCK_DGRAM);protocol:通讯协定(如果使用者不指定则设为0);注释:如果要建立的是遵从TCP/IP协议的socket,第二个参数type应为SOCK_STREAM,如为UDP(数据报)的socket,应为SOCK_DGRAM。recv():从一个套接口接收数据。语法:intPASCALFARrecv(SOCKETs,charFAR*buf,intlen,intflags);参数:s:一个标识已连接套接口的描述字。buf:用于接收数据的缓冲区。len:缓冲区长度。flags:指定调用方式。注释:本函数用于已连接的数据报或流式套接口s进行数据的接收。对SOCK_STREAM类型的套接口来说,本函数将返回所有可用的信息,最大可达缓冲区的大小。如果套接口被设置为线内接收带外数据(选项为SO_OOBINLINE),且有带外数据未读入,则返回带外数据。应用程序可通过调用ioctlsocket()的SOCATMARK命令来确定是否有带外数据待读入。对于数据报类套接口,队列中第一个数据报中的数据被解包,但最多不超过缓冲区的大小。如果数据报大于缓冲区,那么缓冲区中只有数据报的前面部分,其他的数据都丢失了,并且recv()函数返回WSAEMSGSIZE错误。如果没有数据待读,那么除非是非阻塞模式,不然的话套接口将一直等待数据的到来,此时将返回SOCKET_ERROR错误,错误代码是WSAEWOULDBLOCK。用select()或WSAAsynSelect()可以获知何时数据到达。如果套接口为SOCK_STREAM类型,并且远端“优雅”地中止了连接,那么recv()一个数据也不读取,立即返回。如果立即被强制中止,那么recv()将以WSAECONNRESET错误失败返回。在套接口的所设选项之上,还可用标志位flag来影响函数的执行方式。也就是说,本函数的语义既取决于套接口选项,也取决于标志位参数。标志位可取下列值:MSG_PEEK查看当前数据。数据将被复制到缓冲区中,但并不从输入队列中删除。MSG_OOB处理带外数据(参见2.2.3节具体讨论)。返回值:若无错误发生,recv()返回读入的字节数。如果连接已中止,返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。错误代码:WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。WSAENOTCONN:套接口未连接。WSAEINTR:阻塞进程被WSACancelBlockingCall()取消。WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。WSAENOTSOCK:描述字不是一个套接口。WSAEOPNOTSUPP:指定了MSG_OOB,但套接口不是SOCK_STREAM类型的WSAESHUTDOWN:套接口已被关闭。当一个套接口以0或2的how参数调用shutdown()关闭后,无法再用recv()接收数据。WSAEWOULDBLOCK:套接口标识为非阻塞模式,但接收操作会产生阻塞。WSAEMSGSIZE:数据报太大无法全部装入缓冲区,故被剪切。WSAEINVAL:套接口未用bind()进行捆绑。WSAECONNABORTED:由于超时或其他原因,虚电路失效。WSAECONNRESET:远端强制中止了虚电路。send():向一个已连接的套接口发送数据。语法:intPASCALFARsend(SOCKETs,constcharFAR*buf,intlen,intflags);参数:s:一个用于标识已连接套接口的描述字。buf:包含待发送数据的缓冲区。len:缓冲区中数据的长度。flags:调用执行方式。注释:send()适用于已连接的数据报或流式套接口发送数据。对于数据报类套接口,必需注意发送数据长度不应超过通讯子网的IP包最大长度。IP包最大长度在WSAStartup()调用返回的WSAData的iMaxUdpDg元素中。如果数据太长无法自动通过下层协议,则返回WSAEMSGSIZE错误,数据不会被发送。请注意成功地完成send()调用并不意味着数据传送到达。如果传送系统的缓冲区空间不够保存需传送的数据,除非套接口处于非阻塞I/O方式,否则send()将阻塞。对于非阻塞SOCK_STREAM类型的套接口,实际写的数据数目可能在1到所需大小之间,其值取决于本地和远端主机的缓冲区大小。可用select()调用来确定何时能够进一步发送数据。在相关套接口的选项之上,还可通过标志位flag来影响函数的执行方式。也就是说,本函数的语义既取决于套接口的选项也取决于标志位。后者由以下一些值组成:MSG_DONTROUTE指明数据不选径。一个WINDOWS套接口供应商可以忽略此标志;参见2.4节中关于SO_DONTROUTE的讨论。MSG_OOB发送带外数据(仅适用于SO_STREAM;参见2.2.3节)。返回值:若无错误发生,send()返回所发送数据的总数(请注意这个数字可能小于len中所规定的大小)。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。错误代码:WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。WSAEACESS:要求地址为广播地址,但相关标志未能正确设置。WSAEINTR:通过一个WSACancelBlockingCall()来取消一个(阻塞的)调用。WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。WSAEFAULT:buf参数不在用户地址空间中的有效位置。WSAENETRESET:由于WINDOWS套接口实现放弃了连接,故该连接必需被复位。WSAENOBUFS:WINDOWS套接口实现报告一个缓冲区死锁。WSAENOTCONN:套接口未被连接。WSAENOTSOCK:描述字不是一个套接口。WSAEOPNOTSUPP:已设置了MSG_OOB,但套接口非SOCK_STREAM类型。WSAESHUTDOWN:套接口已被关闭。一个套接口以1或2的how参数调用shutdown()关闭后,无法再用sned()函数。WSAEWOULDBLOCK:WSAEMSGSIZE:套接口为SOCK_DGRAM类型,且数据报大于WINDOWS套接口实现所支持的最大值。WSAEINVAL:套接口未用bind()捆绑。WSAECONNABORTED:由于超时或其他原因引起虚电路的中断。WSAECONNRESET:虚电路被远端复位。WSAAsyncSelect():通知套接口有请求事件发生.语法:intPASCALFARWSAAsyncSelect(SOCKETs,HWNDhWnd,unsignedintwMsg,longlEvent);参数:s标识一个需要事件通知的套接口的描述符.hWnd标识一个在网络事件发生时需要接收消息的窗口句柄.wMsg在网络事件发生时要接收的消息.lEvent位屏蔽码,用于指明应用程序感兴趣的网络事件集合.注释:本函数用来请求WindowsSocketsDLL为窗口句柄发一条消息-无论它何时检测到由lEvent参数指明的网络事件.要发送的消息由wMsg参数标明.被通知的套接口由s标识.本函数自动将套接口设置为非阻塞模式.lEvent参数由下表中列出的值组成.值意义FD_READ欲接收读准备好的通知.FD_WRITE欲接收写准备好的通知.FD_OOB欲接收带边数据到达的通知.FD_ACCEPT欲接收将要连接的通知.FD_CONNECT欲接收已连接好的通知.FD_CLOSE欲接收套接口关闭的通知.启动一个WSAAsyncSelect()将使为同一个套接口启动的所有先前的WSAAsyncSelect()作废.例如,要接收读写通知,应用程序必须同时用FD_READ和FD_WRITE调用WSAAsyncSelect(),如下:rc=WSAAsyncSelect(s,hWnd,wMsg,FD_READ|FD_WRITE);对不同的事件区分不同的消息是不可能的.下面的代码将不会工作;第二个调用将会使第一次调用的作用失效,只有FD_WRITE会通过wMsg2消息通知到.rc=WSAAsyncSelect(s,hWnd,wMsg1,FD_READ);rc=WSAAsyncSelect(s,hWnd,wMsg2,FD_WRITE);如果要取消所有的通知,也就是指出WindowsSockets的实现不再在套接口上发送任何和网络事件相关的消息,则lEvent应置为0.rc=WSAAsyncSelect(s,hWnd,0,0);尽管在本例中,WSAAsyncSelect()立即使传给该套接口的事件消息无效,仍有可能有消息等在应用程序的消息队列中.应用程序因此也必须仍准备好接收网络消息-即使消息作废.用closesocket()关闭一个套接口也同样使WSAAsyncSelect()发送的消息作废,但在closesocke()之前队列中的消息仍然起作用.由于一个已调用accept()的套接口和用来接收它的侦听套接口有同样的属性,任何为侦听套接口设置的的WSAAsyncSelect()事件也同样对已接收的套接口起作用.例如,如果一个侦听的套接口有WSAAsyncSelect()事件FD_ACCEPT,FD_READ,FD_WRITE,则任何在那个侦听的套接口上接收的套接口将也有FD_ACCEPT,FD_READ,FD_WRITE事件,以及同样的wMsg的值.若需要不同的wMsg及事件,应用程序应调用WSAAsyncSelect(),将已接收的套接口和想要发送的新消息作为参数传递.当某一套接口s上发生了一个已命名的网络事件,应用程序窗口hWnd会接收到消息wMsg.wParam参数标识了网络事件发生的套接口.lParam的低字指明了发生的网络事件.lParam的高字则含有一个错误代码.该错误代码可以是winsock.h中定义的任何错误.错误代码和事件可以通过WSAGETSELECTERRORH和WSAGETSELECTEVENT宏从lParam中取出.定义如下:#defineWSAGETSELECTERROR(lParam)HIWORD(lParam)#defineWSAGETSELECTEVENT(lParam)LOWORD(lParam)注意:在accept()调用和为改变事件或wMsg的WSAAsyncSelect()调用中有一个计时窗口.应用程序如果需要给侦听的和调用过accept()的套接口以不同的wMsg,它就应该在侦听的套接口上请求FD_ACCEPT事件,然后在accept()调用后设置相应的事件.由于FD_ACCEPT从不发送给已连接的套接口,而FD_READ,FD_WRITE,FD_OOB及FD_CLOSE也从不发送给侦听套接口,所以不会产生困难.使用以上的宏将最大限度的提高应用程序的可移植性.返回的可能网络事件如下:值意义FD_READ套接口s准备读FD_WRITE套接口s准备写FD_OOB带外数据准备好在套接口s上读.FD_ACCEPT套接口s准备接收新的将要到来的连接.FD_CONNECT套接口s上的连接完成.FD_CLOSE由套接口s标识的连接已关闭.返回值:0若应用程序感兴趣的网络事件的声明成功.SOCKET_ERROR否则.可通过调用WSAGetLastError()返回特定的错误代码.错误代码:WSANOTINITIALISED在使用本API前必须进行一次成功的WSAStartup()调用.WSAENETDOWNWINDOWSSOCKETS实现已检测到网络子系统故障.WSAEINVAL指出指定的参数之一是非法的.WSAEINPROGRESS一个阻塞的WindowsSockets操作正在进行.附加的错误代码可能在应用程序窗口接收到消息时被置.这些代码可以用WSAGETSELECTERROR宏从lParam中取出.对应于每个网络事件的可能错误代码为:事件:FD_CONNECTWSAEADDRINUSE给定的地址已被使用.WSAEADDRNOTAVAIL指定的地址在本地机器不能使用.WSAEAFNOSUPPORT指定族的地址不能和本套接口同时使用.WSAECONNREFUSED连接的

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论