网络接口编程复习资料.docx
- 文档编号:8208026
- 上传时间:2023-01-29
- 格式:DOCX
- 页数:16
- 大小:105.28KB
网络接口编程复习资料.docx
《网络接口编程复习资料.docx》由会员分享,可在线阅读,更多相关《网络接口编程复习资料.docx(16页珍藏版)》请在冰豆网上搜索。
网络接口编程复习资料
Winsock是什么?
Windows下网络编程的规范,Windows下得到广泛应用的、开放的、支持多种协议的网络编程接口。
已成为Windows网络编程的事实上的标准。
Windowssocket规范
WindowsSocket规范本意在于提供给应用程序开发者一套简单的API,并让各家网络软件供应商共同遵守。
Socket原理
Socket通常称为套接字、套管、插口,是两个程序间通信链路的端点。
Socket实际上是一个编程接口,为网络应用程序提供各种接口函数。
Winsock基本概念
多数网络协议都由软件实现,而且几乎所有计算机系统都将网络协议的实现作为操作系统的一部分,操作系统提供给用户的程序接口叫做应用程序编程接口(API)。
套接字接口(SocketInterface)就是一种API
套接字及类型
套接字(socket)是网络通信的基本构件,是可以被命名和寻址的通信端点,使用中的每一个套接字都有其类型和与之相连的进程。
套接字存在于通信区域中,通信区域也称地址族
套接字通常只与同一区域中的套接字交换数据(也可跨区域通信,但要执行某种转换进程之后才能实现)。
TCP/IP的socket提供三种类型的套接字:
流式套接字(SOCK_STREAM)
提供一个面向连接的、可靠的数据传输服务,内设流量控制,避免数据流超限;数据被看作是字节流,无长度限制。
文件传输协议(FTP)即使用流式套接字。
数据报式套接字(SOCK_DGRAM)
提供一个无连接服务。
数据报以独立包形式被发送,不提供无错保证,数据可能丢失或重复,且接收顺序混乱。
网络文件系统(NFS)使用数据报式套接字。
原始式套接字(SOCK_RAW)
该接口允许对较低层协议,如IP、ICMP直接访问。
常用于检验新的协议实现或访问现有服务中配置的新设备。
服务方式
面向连接(虚电路)
面向连接服务是电话系统服务模式的抽象,每一次完整的数据传输都要经过建立连接、使用连接、终止连接的过程。
在数据传输过程中,不携带目的地址,而使用连接号(connectID)。
本质上,连接是一个管道,收发数据不但顺序一致,而且内容相同。
TCP协议提供面向连接的虚电路。
无连接
无连接服务是邮政系统服务的抽象,每个分组都携带完整的目的地址,各分组在系统中独立传送。
无连接服务不能保证分组的先后顺序,不进行分组出错的恢复和重传,不保证传输的可靠性。
UDP协议提供无连接的数据报服务。
Winsock寻址
计算机都分配有一个IP地址,用一个32位数来表示。
客户机需要通过TCP或UDP和服务器通信时,必须指定服务器的IP地址和服务端口号。
服务器打算监听接入客户机请求时,也必须指定一个IP地址和一个端口号。
编写Winsock通信程序需要那些头文件和动态连接库?
winsock2.h,ws2_32.lib
TCP和UDP通信使用的API函数
socket()、bind()、listen()、accept()、send()、recv()、sendto()、recvfrom()、closesocket()
Connect()函数的说明
在客户端使用该函数请求建立连接时,将激活建立连接的三次握手,用来建立到服务器TCP的连接。
如果调用该函数前没有调用bind()来绑定本地地址,则由系统隐式绑定一个地址到该套接字
该函数用在UDP的客户端时,connect()函数并不是真正地发出建立请求连接的请求,调用将从本地操作系统直接返回。
这样可以将服务器的地址信息保存下来,在后续UDP端口发送数据时,由套接字自动在发送函数中填入服务器地址,而不需要由应用程序在调用发送函数时填入
面向连接的C/S程序工作流程(TCP)
服务器端工作流程
使用WSAStartup()加载Winsock库
使用socket()函数创建服务器端通信套接字
使用bind()函数将创建的套接字与服务器地址绑定
使用listen()函数使服务器套接字做好接收连接请求准备
使用accept()接收来自客户端由connect()函数发出的连接请求
根据连接请求建立连接后,使用send()函数发送数据,或者使用recv()函数接收数据
使用closesocket()函数关闭套接字(可以先用shutdown()函数先关闭读写通道)
最后调用WSACleanup()函数释放Winsock库
客户端程序工作流程
使用WSAStartup()函数加载Winsock库
使用socket()函数创建客户端套接字
使用connect()函数发出向服务器建立连接的请求(调用前可以不用bind()端口号,由系统自动完成)
连接建立后使用send()函数发送数据,或使用recv()函数接收数据
使用closesocet()函数关闭套接字
最后调用WSACleanup()函数释放Winsock库
无连接的C/S程序工作流程(UDP)
无连接的数据报传输服务通信时,客户端与服务器端所使用的函数是类似的,其工作流程如下:
使用WSAStartup()函数加载Winsock库
使用socket()函数创建套接字,以确定协议类型
调用bind()函数将创建的套接字与本地地址绑定,确定本地地址和本地端口号
使用sendto()函数发送数据,或者使用recvfrom()函数接收数据
使用closesocket()函数关闭套接字
调用WSACleanup()函数释放Winsock库
UDP通信程序如何获取对方的地址信息?
在发送的时候若是广播的话是不会有对方IP地址的,一般用send进行发送,若是定点发送的话是可以将对方IP地址确定的
UDP通信程序是不是一定要绑定套接字到本地地址?
不一定
UDP通信程序是否可以调用connect()?
如果没有预先绑定地址和端口,要先发送数据之后,才能确定己方UDP采用的地址和端口,因为地址和端口是第一次发送数据时分配的。
如果不想通过发送数据来确定地址和端口,可以调用connect函数,不过这样以后该SOCKET只能跟connect函数中指定的端口和地址通信了。
套接字模式
Winsock提供了两种套接字模式:
阻塞和非阻塞模。
Windows平台支持套接字以两种工作。
在阻塞模式下,在I/O操作完成前,执行操作的Winsock函数会一直等候下去,不会立即返回。
非阻塞模式下,Winsock函数会立即返回。
阻塞模式,在一个阻塞套接字上调用任何一个WinsockAPI函数,都会产生相同的后果——“等待”。
大多数Winsock应用都是遵照一种“生产者-消费者”模型来编制的。
在这种模型中,应用程序需要读取(或写入)指定数量的数据,然后以它为基础执行一些计算。
为了防止由于数据的缺乏造成应用程序完全陷于“凝固”状态,同时不必连续性地检查系统网络缓冲。
可采用如下方法
将应用程序划分为一个读线程,以及一个计算线程,两个线程都共享同一个数据缓冲区。
对这个缓冲区的访问需要受到一定的限制,用同步对象来控制访问,比如Mutex。
读线程从网络连续地读入数据,并将其置入共享缓冲区内。
读线程取得计算线程开始工作至少需要的数据量后,便触发一个事件,通知计算线程。
随后,计算线程从缓冲区取走(删除)一个数据块,然后进行计算。
非阻塞模式
非阻塞模式套接字除具备阻塞套接字已有的各项优点之外,还进行了少许扩充,功能更强。
套接字工作在非阻塞模式时,WinsockAPI调用会立即返回。
大多数情况下,这些调用都会“失败”,并返回一个WSAEWOULDBLOCK错误。
设置非阻塞套接字
阻塞与非阻塞通信小结
通信包括阻塞和非阻塞两种模式。
对于不同的协议,阻塞通信和非阻塞通信有不同的表现。
对于UDP协议,由于UDP没有发送缓存,因此所有UDP协议即使在阻塞模式下也不会发生阻塞。
对于面向连接的协议,连接建立阶段,阻塞与非阻塞也表现不一。
在阻塞模式下,如果没有连接请求到达,则等待连接调用将阻塞直到有连接请求到达;但在非阻塞模式下,如果没有连接请求到达,等待连接调用将直接返回。
在连接建立阶段,不管是阻塞模式还是非阻塞模式,发起连接请求的一方总是会使调用它的进程阻塞,阻塞间隔最少等于到达服务器的一次往返时间。
通信模式对应用程序的设计方法也有直接的影响。
在非阻塞模式下,应用程序必须不断地轮询是否有数据到达或有连接请求到达。
这种轮询的方式耗费的CPU资源较大,要尽可能避免使用,而在阻塞模式下则不存在这一问题,但其缺点是进程或线程在执行I/O操作时将被阻塞而不能执行其他的工作,因此在单进程或单线程应用中不能使用这种模式。
在多线程应用中比较适合用阻塞模式,一个线程被阻塞不影响其他线程的工作。
套接字I/O模型
Select模型,WSAAsynSelect模型,WSAEventSelect模型,重叠模型,完成端口模型。
Select模型
Select模型是WinSock中最常见的I/O模型。
通过调用Select函数可以确定一个或多个套接字的状态,判断套接字上是否存在数据,或者能否向一个套接字写入数据。
既能防止应用程序在套接字处于阻塞模式时,在一次I/O操作后被阻塞,同时也能防止在套接字处于非阻塞模式时,产生WSAEWOULDBLOCK错误。
使用select模型的编程步骤:
建立fd_set集合s,用来存放欲使用的套接字。
将套接字添加到集合s中。
确定要检查的套接字集合Xi(1=
使用FD_ZERO宏,初始化Xi。
使用FD_SET宏,根据需要将套接字句柄添加到Xi中
调用select函数
根据select函数的返回值进行处理,当成功返回时,判断s中套接字是否在Xi中,并进行相应处理(处理时可能要添加新的套接字到s中)
回到6
select模型的优点:
可以在单线程内管理多个套接字,最大套接字数量取决于FD_SETSIZE的大小,Winsock2.h中定义为64,用户也可自行定义,但不能超过1024。
缺点:
调用select前后对所有套接字都要进行遍历操作,以便设置和检查。
当FD_SETSIZE太大时,服务器性能明显下降。
WSAAsyncSelect模型
WSAAsyncSelect模型是WinSock中另一个常用的异步I/O模型。
该模型可在套接字上接收以Windows消息为基础的网络事件通知。
调用WSAAsyncSelect函数自动将套接字设置为非阻塞模式,并向WinSockDLL注册一个或多个感兴趣的网络事件,同时提供接收通知时使用的窗口句柄,当注册的网络事件发生时,对应的窗口将收到一个基于消息的通知。
问题1:
对监听套接字和连接套接字应如何设置通知码?
监听套接字:
WSAAsyncSelect(s,hWnd,WM_SOCKET,FD_ACCEPT|FD_CLOSE);
连接套接字:
WSAAsyncSelect(s,hWnd,WM_SOCKET,FD_READ|FD_WRITE|FD_CLOSE)
使用WSAAsyncSelect模型编程步骤:
winsock初始化
自定义WM_SOCKET消息
创建窗口
创建套接字
调用WSAAsyncSelect()
编写WindowProc()
WSAEventSelect模型
WSAEventSelect模型是WinSock提供的另一个异步I/O模型,与WSAAsyncSelect模型类似,也允许应用程序在一个或多个套接字上接收以事件为基础的网络事件通知,并且支持的网络事件与WSAAsyncSelect模型一样。
与WSAAsyncSelect模型的主要区别在于网络事件会被发送到一个事件对象句柄,而不是发送到一个窗口。
WSAEventSelect优缺点
优点:
简单、不需要窗口环境。
缺点:
事件对象数目受限制,最多64。
由于一个套接字对应一个事件对象,故支持的套接字数量也为64。
基于WSAEventSelect模型的多线程服务器
问题:
单线程的WSAEventSelect服务器容纳的事件对象受限,亦即可以管理的最大套接字数量为64。
思路:
采用多线程,当有新的连接请求到来时,如果一个线程可容纳的连接达到上限(64),创建新的线程处理连接。
程序构成:
主线程负责监听,创建连接套接字,将套接字分配给连接数未达到上限的线程。
为此先介绍两个重要的结构:
SOCKET_OBJ
THREAD_OBJ
重叠模型的基本原理
重叠模型是让应用程序使用重叠数据结构(WSAOVERLAPPED),一次投递一个或多个WinsockI/O操作,在这些提交的I/O操作完成之后,应用程序可以接收到完成通知,从而进行相应的处理。
两种方法可以接收到重叠IO操作的完成的通知:
1. 在事件对象上等待通知(eventobjectnotification)
2. 完成例程(completionroutines),注意:
并不是完成端口
关于缓冲区和重叠操作
对接收方,应用程序使用WSARecv函数或WSARecvFrom函数来提供存放接收数据的缓冲区。
如果数据在网络接收以前,应用程序已经提供了一个或多个缓冲区,那么接收的数据就可以立即存放进用户缓冲区。
如果在应用程序提供数据缓冲区时已经有数据到来,那么接收的数据将被立即拷贝进用户缓冲区。
如果数据到来时,应用程序没有提供接收缓冲区,那么网络将回到同步操作方式,传送过来的数据将被存放进内部缓冲区,直到应用程序发出了接收调用并且提供了接收缓冲区,这时接收的数据才被拷贝进接收缓冲区。
特例:
当应用程序使用setsockopt函数把内部接收缓冲区长度设置为0时,对可靠传输协议,数据直到应用程序提供了接收缓冲区后才被接收,而对不可靠传输协议,数据将会丢失。
对发送方,应用程序使用WSASend函数或WSASendTo函数提供一个指向已填充的数据缓冲区的指针。
应用程序不应在网络使用完该缓冲区的数据以前以任何方式破坏该缓冲区的数据。
重叠发送和接收调用会立即返回。
如返回值是0,那么表明I/O操作已经完成,对应的完成指示也可得到。
如果返回值是SOCKET_ERROR,并且错误代码是WSA_IO_PENDING,那么表明重叠操作已经被成功初始化,今后发送缓冲区被用完或者接收缓冲区有数据时,将会有完成指示。
其他错误代码表明初始化没有成功,今后也不会有完成指示。
发送操作和接收操作都可以被重叠使用。
接收函数可以被多次调用,指定接收缓冲区,准备接收到来的数据。
发送函数也可被多次调用,组成一个发送缓冲区队列。
注意:
应用程序可以通过按顺序提供发送缓冲区来确保一系列重叠发送操作的顺序,而对应的完成指示有可能是按照另外的顺序排列的。
同样,在接收数据的一方,缓冲区是按照被提供的顺序填充的,但是完成指示也可能按照另外的顺序排列。
关联:
SOCKET–WSAOVERLAPPED–WSAEVENT
使用重叠模型的步骤
以接收操作为例:
1、定义相关变量…………
2、创建监听套接字(使用socket()或WSASocket()),并进入监听状态。
3、接受连接请求(使用accept()或AcceptEx())。
4、为新的连接套接字创建WSAOVERLAPPED结构,并分配事件对象句柄。
5、以WSAOVERLAPPED结构为参数,在套接字上投递WSARecv()请求。
6、将所有接收套接字使用的重叠结构上的事件组建成事件数组,并调用WSAWaitForMultipleEvents函数,等待事件受信。
7、使用WSAGetOverlappedResult(),判断重叠调用的返回状态。
8、设置事件对象状态为无信号状态,必要时重新组建事件数组。
9、在套接字上继续投递WSARecv()请求。
10、重复6~9。
几种winsockI/O模型的分析
①select模型:
核心是select()函数,它可用于判断套接字上是否存在数据,或者能否向一个套接字写入数据。
该函数可以有效地防止应用程序在套接字处于阻塞模式时,send或recv进入阻塞状态;同时也可以防止在非阻塞模式产生大量的WSAEWOULDBLOCK错误。
优点:
单线程管理多个套接字
缺点:
调用select()前后都需要对所有套接字进行遍历操作。
②WSAAsyncSelect模型:
以事件为基础使用消息机制,关键在于WSAAsyncSelect()函数,将socket消息发送到窗口上,然后在窗口过程函数中处理相应的FD_READ、FD_WRITE等网络事件。
优点:
1、WSAAsyncSelect和WSAEventSelect模型提供了读写数据能力的异步通知,但不提供数据的异步传输,而重叠及完成端口提供数据的异步传输。
2、可以在系统开销不大的情况下同时处理很多连接,而select模型还需要建立fd_set结构。
缺点:
必须要使用一个窗口接收消息,如果处理成千上万的套接字显得力不从心。
③WSAEventSelect模型:
也是以事件为基础的网络事件通知,但是与WSAAsyncSelect不同的是,主要是由事件对象接收网络事件通知,而不是通过窗口。
优点:
不需要窗口。
缺点:
每次只能等待64个事件,所以处理多个套接字时有必要组织一个线程池。
④重叠模型:
可以使程序能达到更佳的系统性能。
基本设计原理就是让应用程序使用重叠的数据结构,一次投递一个或多个I/O请求。
针对这些提交的请求,在这些请求完成之后,应用程序可作相应的处理。
使用重叠操作,提供了数据的异步传输能力
⑤完成端口:
完成端口提供了最好的伸缩性,往往可以使系统达到最好的性能,是处理成千上万的套接字的首选。
从本质上说,完成端口模型要求创建一个windows完成端口对象,该对象通过指定数量的线程,对重叠I/O请求进行管理,以便为已经完成的重叠I/O请求提供服务。
完成端口I/O模型
I/O完成端口是应用程序使用线程池处理异步I/O请求的一种机制。
处理多个并发异步I/O请求时,使用I/O完成端口比在I/O请求时创建线程更快更有效。
完成端口可接受多种对象句柄。
从本质上说,完成端口模型要求创建一个Win32完成端口对象,通过指定数量的线程,对重叠I/O请求完成情况进行管理,以便为已经完成的重叠I/O请求提供服务。
关闭IOCP
要避免在进行重叠I/O操作的同时,强行释放一个OVERLAPPED结构,最好的办法是针对每个套接字句柄,调用closesocket函数,任何尚未进行的重叠I/O操作都会完成,只不过是失败方式完成。
一旦所有套接字句柄都已关闭,便需在完成端口上终止所有工作线程的运行,则需要使用PostQueuedCompletionStatus()函数,向每个工作线程都发送一个指示每个线程都“立即结束并退出”完成通知包。
完成端口大概的处理流程
创建一个完成端口。
创建一个线程A。
A线程循环调用GetQueuedCompletionStatus()函数来得到IO操作结果。
主线程循环里调用accept等待客户端连接。
主线程里accept返回新连接后,把这个新的套接字句柄用CreateIoCompletionPort()关联到完成端口,然后发出一个异步的WSASend或WSARecv调用,因为是异步函数,WSASend/WSARecv会马上返回,实际的发送或者接收操作由WINDOWS系统去做。
主线程继续下一次循环,阻塞在accept这里等待客户端连接。
WINDOWS系统完成WSASend或者WSArecv的操作,把结果发到完成端口。
A线程里的GetQueuedCompletionStatus()马上返回,并从完成端口取得刚完成的WSASend/WSARecv的结果。
在A线程里对这些数据进行处理(如果处理过程很耗时,需要新开线程处理),然后接着发出WSASend/WSARecv,并继续下一次循环(挂起)在GetQueuedCompletionStatus()这里。
广播通信
广播可以将数据发送给本地子网上的所有机器。
广播通信的缺点:
假如同时有许多进程发送广播数据,网络立刻就会拥挤不堪,造成网络性能大打折扣,甚至有可能陷入瘫痪。
广播发送首先启用广播选项,然后使用广播地址并指定一个端口号,在该端口上发送数据;类似的,接收端也必须对应端口接收广播数据。
接收广播先绑定到本地地址然后使用接收函数接收广播数据,比如recvfrom或WSARecvfrom。
IP多播
“多播”亦称“多点传送”(Multicasting),数据从一个成员送出,然后复制给其他多个成员的技术。
采用这种技术,可有效减轻网络通信的负担,避免资源的无谓浪费。
支持多播通信的平台。
多播通信具有两个层面的重要特征:
控制层面和数据层面。
“控制层面”(ControlPlane)定义了组成员的组织方式;
“数据层面”(DataPlane)决定了在不同的成员之间,数据如何传送。
控制层面和数据层面这两方面的特征既可以是“有根的”(Rooted),也可以是“无根的”(Nonrooted)。
组管理协议(IGMP)
管理多播成员以及成员之间的关系。
多播主机利用IGMP通知本地多播路由器自己加入一个特定的多播组。
多播路由器利用IGMP协议查询多播组内成员是否还在组内以决定今后是否转发数据到成员。
IGMP是IP多播方案的基础。
实现IP多播通信的基本步骤:
1)用socket函数创建一个套接字,注意套接字类型要设为SOCK_DGRAM。
2)如果想从组内接收数据,请将套接字同一个本地端口绑定到一起。
3)调用setsockopt函数,同时设置IP_ADD_MEMBERSHIP选项,指定想加入的那个组的地址结构。
如使用Winsock2,那么步骤1)和2)是相同的,只是步骤3)换成调用WSAJoinLeaf函数,将自己加入那个组。
使用原始套接字可以做什么?
实现一些实用工具(ping,traceroute)。
可对IP头,TCP头,UDP头,ICMP头等进行操作。
1、编写基于TCP的C/S程序,服务器和客户端程序的基本流程是怎样的?
使用API函数给出框架代码。
//初始化WS2_32.dll
WSADATAwsaData;
WSAStartup(MAKEWORD(2,2),&wsaData);
//创建监听套接字
SOCKETsListen=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
//填充sockaddr_in结构
sockaddr_insin;
sin.sin_family=AF_INET;
sin.sin_port=htons(4567);
sin.sin_addr.S_un.S_addr=INADDR_ANY;
//绑定监听套接字到一个本地地址
if(bind(sListen,(LPSOCKADDR)&sin,sizeof(sin))==SOCKET_ERROR)
return0;
//进入监听模式
if(listen(sListen,2)==SOCKET_ERROR)return0;
//循环接受客户的连接请求
charbuffer[128]=“1234567”
sockaddr_inremoteAddr;
intnAddrLen=sizeof(remoteAddr);
SOCKETsClient;
while(TRUE)
{//接受一个新连接
sClient=
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 网络 接口 编程 复习资料