标准TCPIP编程接口-Socket.ppt

上传人:牧羊曲112 文档编号:6365601 上传时间:2023-10-21 格式:PPT 页数:100 大小:315.99KB
返回 下载 相关 举报
标准TCPIP编程接口-Socket.ppt_第1页
第1页 / 共100页
标准TCPIP编程接口-Socket.ppt_第2页
第2页 / 共100页
标准TCPIP编程接口-Socket.ppt_第3页
第3页 / 共100页
标准TCPIP编程接口-Socket.ppt_第4页
第4页 / 共100页
标准TCPIP编程接口-Socket.ppt_第5页
第5页 / 共100页
点击查看更多>>
资源描述

《标准TCPIP编程接口-Socket.ppt》由会员分享,可在线阅读,更多相关《标准TCPIP编程接口-Socket.ppt(100页珍藏版)》请在三一办公上搜索。

1、第17章 标准TCP/IP编程接口 Socket,第17章 标准TCP/IP编程接口 Socket,17.1 套接口概述17.2 地址与地址操作函数17.2.1 INET协议族地址结构sockaddr_in17.2.2 IPv4地址结构in_addr17.2.3 通用地址结构sockaddr17.2.4 地址操作函数17.3 端口17.4 字节序问题17.5 三种套接口类型和两种I/O模式17.5.1 套接口的类型17.5.2 I/O模式,第17章 标准TCP/IP编程接口Socket,17.6 基本套接口函数 17.7 简单的客户端程序17.6.1 WSAStartup 17.7.1 UDP

2、客户端17.6.2 socket 17.7.2 TCP客户端17.6.3 bind17.6.4 listen.17.6.5 accept17.6.6 conect17.6.7 recv和send17.6.8 recvfrom和sendto17.6.9 closesocket17.6.10 WSACleanup,17.1 套接口概述,Berkeley sockets 接口在windows平台上的移植版本称为Winsock。最初的伯克利套接口API在windows平台上的移植版本是Winsock1.1,在它的基础上,微软又进一步提供了Winsock2.0从用户的角度来看,套接口是网络通信端点的一种

3、抽象概念,为用户提供一种发送和接收数据的机制。是一种进程间通信的机制,适用于分布式环境。,17.2.1 INET协议地址结构sockaddr_in,struct sockaddr_inShort sin_family;U_short sin_port;Struct in_addr sin_addr;Char sin_zero8;,地址族,一般填AF_INET,16位IP端口,32位IP地址,8个字节的0填充,给结构体初始化清0的函数如下Void*memset(void*dest,int c,size_t count);,所以是TCP/IP,17.2.2 IPv4地址结构in_addr,stru

4、ct in_addrUnionstructu_char s_b1,s_b2,s_b3,s_b4;s_un_b;structu_short s_w1,s_w2;s_un_w;u_long s_addr;s_un;#define;如多网卡,又不关心接口(INADDR_ANY的使用,P184),赋值时的不同分段(4、2、1),INET协议地址结构中的IP地址部分,17.2.3 通用地址结构sockaddr,struct sockaddru_short sa_family;char sa_data14;一种是只为TCP/IP,另外是为了提供通用接口以服务多种网络协议开发的通用结构,但要提供足够的信息说

5、明自己的协议,复杂!例如:Int connetct(socket s,const struct sockaddr FAR*name,int namelen)对于程序员来说,很少直接使用这种通用地址结构。,连接时不是struct sockadr_in*而是通用地址结构,17.2.4 地址操作函数,3个常用的地址操作函数:将点分格式的IPv4地址字符串转化为in_addr地址结构适用的32位整数:unsigned long inet_addr(const char FAR*cp);将in_addr地址值转化为标准的点分IP地址字符串:char FAR*inet_ntoa(struct in_add

6、r in);域名解析功能:struct hostent FAR*gethostbyname(const char FAR*name);注意:在使用winsock函数之前,应用程序必须首先调用WSAStartup函数初始化ws2_32.dll,而在应用结束后必须调用WSACleanup函数关闭。,Hostent结构,struct hostent char FAR*h_name;/*official name of host*/char FAR*FAR*h_aliases;/*alias list*/short h_addrtype;/*host address type*/short h_len

7、gth;/*length of address*/char FAR*FAR*h_addr_list;/*list of addresses*/#define h_addr h_addr_list0/*address,for backward compat*/;,17.3 端口,0:不使用11023:知名端口10245000:可以被任意客户端程序使用500165535:为其他服务器程序预留,17.4 字节序问题,字节顺序转换htons()Host to Network Short“(16bit)htonl()Host to Network Long“(32bit)ntohs()Network t

8、o Host Shortntohl()Network to Host Long连接过程是通过一系列状态表示的,这些状态有:LISTEN,SYN-SENT,SYN-RECEIVED,ESTABLISHED,FIN-WAIT-1,FIN-WAIT-2,CLOSE-WAIT,CLOSING,LAST-ACK,TIME-WAIT 和CLOSED。,17.5.1 三种套接口类型,流套接口(SOCK_STREAM)面向连接的TCP数据报套接口(SOCK_DGRAM)无连接的UDP原始套接口(SOCK_RAW)可以读写ICMP、IGMP报文,可以用于从IP头起构造自己的报文。,17.5.2 I/O模式,非阻

9、塞套接字是指执行此套接字的网络调用时,不管是否执行成功,都立即返回。比如调用某个函数读取网络缓冲区中数据,不管是否读到数据都立即返回,而不会一直挂在此函数调用上。阻塞调用是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回。,17.5.2 I/O模式,简明扼要的来说可以打个比方:你有数个同学来访,有若干数据需要收取:1、你时不时的去门口看看,没有看到你同学的话就回客厅等待,看到同学就接到客厅来,非阻塞模式,无论收到数据与否都返回。2、你一直在门口等着你同学,接到后才回客厅,阻塞模式,接收到数据后才返回。,17.5.2 I/O模式,阻塞(BLOCK):便于使用非阻塞(NONBL

10、OCK):效率较高默认情况下,Winsock函数都以阻塞模式工作,17.6 基本套接口函数,例如:TCP服务器程序流程:初始化Winsock创建一个Socket绑定并监听本地的特定端口accept接收客户端的连接在accept操作返回的Socket上进行数据通信关闭Socket最后结束Winsock的使用,17.6 基本套接口函数,WSAStartupSocketBindListenAcceptConnectrecv和sendrecvfrom和sendtoClosesocketWSACleanup,17.6.1 WSAStartup,简述:#include int WSAStartup(WOR

11、D wVersionRequested,LPWSADATA lpWSAData);wVersionRequested:应用程序需要的最高版本,双字节数值型,高位字节指出副版本(修正)号,低位字节指明主版本号。lpWSAData:指向WSADATA数据结构的指针,用来接收Windows Sockets实现的信息。,17.6.1 WSAStartup,注释:WSAStartup()函数必须是应用程序或DLL调用的第一个Winsock函数。成功调用之后才能进一步的调用别的Winsock函数。它允许应用程序或DLL指明Windows Sockets API的版本号及获得特定Windows Socket

12、s实现的细节。,17.6.1 WSAStartup,注释:WSAStartup()的调用过程一方面是初始化ws2_32.dll。另一方面和Winsock库进行版本协商,只有要求的版本=系统支持的最低版本(下限)才成功。并且在wHighVersion中返回系统支持的最高版本,在wVersion中返回系统支持的高版本(上限)和wVersionRequested中的较小者。然后Winsock库就会假设应用程序将使用wVersion。如果WSDATA结构中的wVersion域对调用方来说不可接收,要么去另一个Windows Sockets DLL中搜索,要么初始化失败。,17.6.1 WSAStart

13、up,本协议允许Windows Sockets DLL和Windows Sockets应用程序共同支持一定范围的Windows Sockets版本。如果版本范围有重叠,应用程序就可以成功地使用Windows Sockets DLL。后面的图表给出了WSAStartup()在不同的应用程序和Windows Sockets DLL版本中是如何工作的:,17.6.1 WSAStartup,17.6.1 WSAStartup,返回值:0:成功 否则返回错误代码 注意通常依靠应用程序调用WSAGetLastError()机制获得的错误代码可能不完全,因为Windows Sockets DLL可能没有建立

14、“上一错误”信息储存的客户数据区域。,17.6.1 WSAStartup,错误代码:WSASYSNOTREADY:指出网络通信依赖的网络子系统还没有准备好。WSAVERNOTSUPPORTED:所需的Windows Sockets API的版本未由特定的Windows Sockets实现提供。WSAEINVAL:应用程序指出的Windows Sockets版本不被该DLL支持。,17.6.1 WSAStartup,示例:#pragma comment(lib,“ws2_32.lib”)#include#include Int main(int arge,char*argv)WORD wVers

15、ionReq=MAKEWORD(0,1);/*希望使用0.1版本*/WSAData wsaData;int ret=WSAStartup(wVersionReq,17.6.2 socket,功能:使用前创建一个新的套接字 定义:SOCKET socket(int af,int type,int protocol);返回值:非负整数描述符表示成功,-1表示出错Af指定协议族,一般设为AF_INET,对应internet。Type有三种类型Protocol指定所用的协议,在TCP或UDP编程的时候都取0。,17.6.2 socket,示例:SOCKET sock=socket(AF_INET,SO

16、CK_STREAM,0);SOCKET sock=socket(AF_INET,SOCK_DGREAM,0);SOCKET sock=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);例如:创建套接字(TCP)不成功就提示if(socket(AF_INET,SOCK_STREAM,0)0)fprintf(stderr,“socket creating errorn”);exit(1);,17.6.3 bind,简述:本函数将一本地的传输层地址与已经创建的套接口联系起来,一般来说,作为客户端程序,不用关心它的本地地址是什么,也就没有必要调用bind函数,系统会在通信前自

17、动选择一个本地地址(10245000)。但服务进程则必须绑定到一个为客户端所知的地址上。,17.6.3 bind,#include int bind(SOCKET s,const struct sockaddr FAR*name,int namelen);s:标识一未捆绑套接口的描述字name:赋予套接口的地址。sockaddr结构定义如下:struct sockaddr u_short sa_family;char sa_data14;namelen:name名字的长度,17.6.3 bind,注释:本函数适用于未连接的数据报或流类套接口,在connect()或listen()调用前使用。当

18、用socket()创建套接口后,它便存在于一个名字空间(地址族)中,但并未赋名。bind()函数通过给一个未命名套接口分配一个本地名字来为套接口建立本地捆绑(主机地址/端口号)。,17.6.3 bind,注释:在Internet地址族中,一个名字包括几个组成部分,对于SOCK_DGREAM和SOCK_STREAM类套接口,名字由三部分组成:主机地址,协议号(显式设置为UDP和TCP)和用以区分应用的端口号。如果一个应用并不关心分配给它的地址,则可将Internet地址设置为INADDR_ANY,或将端口号置为0。如果Internet地址段为INADDR_ANY,则可使用任意网络接口;在有多种主

19、机环境下可简化编程。如果端口号置为0,则WINDOWS套接口实现将给应用程序分配一个值在1024到5000之间的唯一的端口。应用程序可在bind()后用getsockname()来获知所分配的地址,但必需注意的是,getsockname()只有在套接口连接成功后才会填写Internet地址,这是由于在多种主机环境下若干种Internet地址都是有效的。,17.6.3 bind,返回值:如无错误发生,则bind()返回0。否则的话,将返回SOCKET_ERROR,应用程序可通过WSAGetLastError()获取相应错误代码。,17.6.3 bind,错误代码:WSANOTINITIALISE

20、D:在使用此API之前应首先成功地调用WSAStartup()。WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。WSAEADDRINUSE:所定端口已在使用中(参见setoption()中的SO_REUSEADDR选项)。,17.6.3 bind,错误代码:WSAEFAULT:namelen参数太小(小于sockaddr结构的大小)。WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。WSAEAFNOSUPPORT:本协议不支持所指定的地址族。WSAEINVAL:该套接口已与一个地址捆绑。WSAENOBUFS:无足够可用缓冲区,连接过多。WSAEN

21、OTSOCK:描述字不是一个套接口。,17.6.3 bind,示例:创建TCP,绑定IP和端口SOCKET sock=socket(AF_INET,SOCK_STREAM,0);Struct sockaddr_in local;Memset(,17.6.3 bind,如果一个应用程序需要把端口捆绑到超过10245000范围的特定端口时,比如rsh需要捆绑到任一保留端口,则可如下编程:SOCKADDR_IN sin;SOCKET s;u_short alport=IPPORT_RESERVED;sin.sin_family=AF_INET;sin.sin_addr.s_addr=0;for(;)

22、sin.sin_port=htons(alport);if(bind(s,(LPSOCKADDR)if(alport=IPPORT_RESERVED/2)/*failall unassigned reserved ports are*/*in use.*/,17.6.4 listen,简述:创建一个套接口并监听申请的连接.#include int listen(SOCKET s,int backlog);S:用于标识一个已捆绑未连接套接口的描述字。backlog:等待连接队列的最大长度。,17.6.4 listen,注释:为了接受连接,先用socket()创建一个套接口,再用listen()为

23、申请进入的连接建立一个后备日志,然后便可用accept()接受连接了。listen()仅适用于支持连接的套接口,如SOCK_STREAM类型的。套接口s处于一种“变动”模式,申请进入的连接请求被确认,并排队等待被接受。这个函数特别适用于同时有多个连接请求的服务器;如果当一个连接请求到来时,队列已满,那么客户将收到一个WSAECONNREFUSED错误。,17.6.4 listen,注释:当没有可用的描述字时,listen()函数仍试图正常地工作。它仍接受请求直至队列变空。当有可用描述字时,后续的一次listen()或accept()调用会将队列按照当前或最近的“后备日志”重新填充,如有可能的话

24、,将恢复监听申请进入的连接请求。,17.6.4 listen,返回值:如无错误发生,listen()返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。,17.6.4 listen,错误代码:WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。WSAEADDRINUSE:试图用listen()去监听一个在使用中的地址。WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。WSAEINVAL:该套

25、接口未用bind()进行捆绑,或已被连接。,17.6.4 listen,错误代码:WSAEISCONN:套接口已被连接。WSAEMFILE:无可用文件描述字。WSAENOBUFS:无可用缓冲区空间。WSAENOTSOCK:描述字不是一个套接口。WSAEOPNOTSUPP:该套接口不正常listen()调用。,17.6.5 accept,简述:在一个套接口接受一个连接。#include SOCKET accept(SOCKET s,struct sockaddr FAR*addr,int FAR*addrlen);s:套接口描述字,该套接口在listen()后监听连接。addr:(可选)指针,指

26、向一缓冲区,其中接收为通讯层所知的连接实体的地址。addr参数的实际格式由套接口创建时所产生的地址族确定。addrlen:(可选)指针,指向存有addr地址长度的整形数。,17.6.5 accept,注释:本函数从s的等待连接队列中抽取第一个连接,创建一个与s同类的新的套接口并返回句柄。如果队列中无等待连接,且套接口为非阻塞方式,则accept()阻塞调用进程直至新的连接出现。如果套接口为非阻塞方式且队列中等待连接,则accept()返回一错误代码。已接受连接的套接口不能用于接受新的连接,原套接口仍保持开放。,17.6.5 accept,注释:addr参数为一个返回参数,其中填写的是为通讯层所

27、知的连接实体地址。addr参数的实际格式由通讯时产生的地址族确定。addrlen参数也是一个返回参数,在调用时初始化为addr所指的地址空间;在调用结束时它包含了实际返回的地址的长度(用字节数表示)。该函数与SOCK_STREAM类型的面向连接的套接口一起使用。如果addr与addrlen中有一个为零NULL,将不返回所接受的套接口远程地址的任何信息。,17.6.5 accept,返回值:如果没有错误产生,则accept()返回一个描述所接受包的SOCKET类型的值。否则的话,返回INVALID_SOCKET错误,应用程序可通过调用WSAGetLastError()来获得特定的错误代码。add

28、rlen所指的整形数初始时包含addr所指地址空间的大小,在返回时它包含实际返回地址的字节长度。,17.6.5 accept,错误代码:WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。WSAEFAULT:addrlen参数太小(小于socket结构的大小)。WSAEINTR:通过一个WSACancelBlockingCall()来取消一个(阻塞的)调用。WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。WSAEINVAL:在accept()前未激活li

29、sten()。WSAEMFILE:调用accept()时队列为空,无可用的描述字。WSAENOBUFS:无可用缓冲区空间。WSAENOTSOCK:描述字不是一个套接口。WSAEOPNOTSUPP:该套接口类型不支持面向连接服务。WSAEWOULDBLOCK:该套接口为非阻塞方式且无连接可供接受。,17.6.5 accept,下面是一个调用accept的例子:struct sockaddr_in ServerSocketAddr;int addrlen;addrlen=sizeof(ServerSocketAddr);ServerSocket=accept(ListenSocket,(struc

30、t sockaddr*),17.6.6 connect,简述:客户端建立与一个服务端的连接。#include int connect(SOCKET s,const struct sockaddr FAR*name,int namelen);s:标识一个未连接套接口的描述字。name:欲进行连接的端口名。namelen:名字长度。,17.6.6 connect,注释:s参数指定一个未连接的数据报或流类套接口。如套接口未被捆绑,则系统赋给本地关联一个唯一的值,且设置套接口为已捆绑。对于流类套接口(SOCK_STREAM类型),函数会引起三次TCP握手,一旦套接口调用成功返回,它就能收发数据了。对于

31、数据报类套接口(SOCK_DGRAM类型),则设置成一个缺省的目的地址,并用它来进行后续的send()与recv()调用。,17.6.6 connect,返回值:若无错误发生,则connect()返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。对阻塞套接口而言,若返回值为SOCKET_ERROR则应用程序调用WSAGetLsatError()。如果它指出错误代码为WSAEWOULDBLOCK,则应用程序可以:1.用select(),通过检查套接口是否可写,来确定连接请求是否完成。2.如果您的应用程序使用基于消息的WSAAsy

32、nSelect()来表示对连接事件的兴趣,则当连接操作完成后,您会收到一个FD_CONNECT消息。,17.6.6 connect,错误代码:WSAENOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。WSAEADDRINUSE:所指的地址已在使用中。WSAEINTR:通过一个WSACancelBlockingCall()来取消一个(阻塞的)调用。WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。WSAEADDRNOTAVAIL:在本地机器上找不到所指的地址。W

33、SAENOTSUPPORT:所指族中地址无法与本套接口一起使用。WSAECONNREFUSED:连接尝试被强制拒绝。WSAEDESTADDREQ:需要目的地址。,17.6.6 connect,错误代码:WSAEFAULT:namelen参数不正确。WSAEINVAL:套接口没有准备好与一地址捆绑。WSAEISCONN:套接口早已连接。WSAEMFILE:无多余文件描述字。WSAENETUNREACH:当前无法从本主机访问网络。WSAENOBUFS:无可用缓冲区。套接口未被连接。WSAENOTSOCK:描述字不是一个套接口。WSAETIMEOUT:超时时间到。WSAEWOULDBLOCK:套接口

34、设置为非阻塞方式且连接不能立即建立。可用select()调用对套接口写,因为select()时会进行连接。,17.6.6 connect,下面是一个例子:struct sockaddr_in daddr;memset(void*)connect(ClientSocket,(struct sockaddr*)&daddr,sizeof(daddr);,17.6.7 recv和send(recv),功能:从一个套接口接收数据可以是面向连接的,必须是已经连接的。也可以是无连接的,但必须是已经绑定的。,17.6.7 recv和send(recv),简述:从一个套接口接收数据。#include int

35、recv(SOCKET s,char FAR*buf,int len,int flags);s:一个标识已连接套接口的描述字。buf:用于接收数据的缓冲区。len:缓冲区长度。flags:指定调用方式。,17.6.7 recv和send(recv),注释:本函数用于已连接的数据报或流式套接口s进行数据的接收。对SOCK_STREAM类型的套接口来说,本函数将返回所有可用的信息,最大可达缓冲区的大小。如果套接口被设置为线内接收带外数据(选项为SO_OOBINLINE),且有带外数据未读入,则返回带外数据。应用程序可通过调用ioctlsocket()的SOCATMARK命令来确定是否有带外数据待读

36、入。,17.6.7 recv和send(recv),注释:对于数据报类套接口,队列中第一个数据报中的数据被解包,但最多不超过缓冲区的大小。如果数据报大于缓冲区,那么缓冲区中只有数据报的前面部分,其他的数据都丢失了,并且recv()函数返回WSAEMSGSIZE错误。如果没有数据待读,那么除非是非阻塞模式,不然的话套接口将一直等待数据的到来,此时将返回SOCKET_ERROR错误,错误代码是WSAEWOULDBLOCK。用select()或WSAAsynSelect()可以获知何时数据到达。,17.6.7 recv和send(recv),如果套接口为SOCK_STREAM类型,并且远端“正常”地

37、中止了连接,那么recv()一个数据也不读取,立即返回。如果被“强制”中止,那么recv()将以WSAECONNRESET错误失败返回。在套接口的所设选项之上,还可用标志位flag来影响函数的执行方式。也就是说,本函数的语义既取决于套接口选项,也取决于标志位参数。标志位可取下列值:,17.6.7 recv和send(recv),返回值:若无错误发生,recv()返回读入的字节数。如果连接已中止,返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。,17.6.7 recv和send(recv),错误代码:WSANOTINITIAL

38、ISED:在使用此API之前应首先成功地调用WSAStartup()。WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。WSAENOTCONN:套接口未连接。WSAEINTR:阻塞进程被WSACancelBlockingCall()取消。WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。WSAENOTSOCK:描述字不是一个套接口。WSAEOPNOTSUPP:指定了MSG_OOB,但套接口不是SOCK_STREAM类型的。WSAESHUTDOWN:套接口已被关闭。当一个套接口以0或2的how参数调用shutdown()关闭后,无法再用recv()接

39、收数据。,17.6.7 recv和send(recv),错误代码:WSAEWOULDBLOCK:套接口标识为非阻塞模式,但接收操作会产生阻塞。WSAEMSGSIZE:数据报太大无法全部装入缓冲区,故被剪切。WSAEINVAL:套接口未用bind()进行捆绑。WSAECONNABORTED:由于超时或其他原因,虚电路失效。WSAECONNRESET:远端强制中止了虚电路。,17.6.7 recv和send(send),简述:向一个已连接的套接口发送数据。#include int send(SOCKET s,const char FAR*buf,int len,int flags);s:一个用于标

40、识已连接套接口的描述字。buf:包含待发送数据的缓冲区。len:缓冲区中数据的长度。flags:调用执行方式。,17.6.7 recv和send(send),注释:send()适用于已连接的数据报或流式套接口发送数据。对于数据报类套接口,必需注意发送数据长度不应超过通讯子网的IP包最大长度。IP包最大长度在WSAStartup()调用返回的WSAData的iMaxUdpDg元素中。如果数据太长无法自动通过下层协议,则返回WSAEMSGSIZE错误,数据不会被发送。,17.6.7 recv和send(send),注释:请注意成功地完成send()调用并不意味着数据传送到达。如果传送系统的缓冲区空

41、间不够保存需传送的数据,除非套接口处于非阻塞I/O方式,否则send()将阻塞。对于非阻塞SOCK_STREAM类型的套接口,实际写的数据数目可能在1到所需大小之间,其值取决于本地和远端主机的缓冲区大小。可用select()调用来确定何时能够进一步发送数据。,17.6.7 recv和send(send),在相关套接口的选项之上,还可通过标志位flag来影响函数的执行方式。也就是说,本函数的语义既取决于套接口的选项也取决于标志位。后者由以下一些值组成:,17.6.7 recv和send(send),返回值:若无错误发生,send()返回所发送数据的总数(请注意这个数字可能小于len中所规定的大小

42、)。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。,17.6.7 recv和send(send),错误代码:WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。WSAEACESS:要求地址为广播地址,但相关标志未能正确设置。WSAEINTR:通过一个WSACancelBlockingCall()来取消一个(阻塞的)调用。WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。WSAEFAULT:bu

43、f参数不在用户地址空间中的有效位置。WSAENETRESET:由于WINDOWS套接口实现放弃了连接,故该连接必需被复位。WSAENOBUFS:WINDOWS套接口实现报告一个缓冲区死锁。WSAENOTCONN:套接口未被连接。WSAENOTSOCK:描述字不是一个套接口。,17.6.7 recv和send(send),错误代码:WSAEOPNOTSUPP:已设置了MSG_OOB,但套接口非SOCK_STREAM类型。WSAESHUTDOWN:套接口已被关闭。一个套接口以1或2的how参数调用shutdown()关闭后,无法再用sned()函数。WSAEWOULDBLOCK:WSAEMSGSI

44、ZE:套接口为SOCK_DGRAM类型,且数据报大于WINDOWS套接口实现所支持的最大值。WSAEINVAL:套接口未用bind()捆绑。WSAECONNABORTED:由于超时或其他原因引起虚电路的中断。WSAECONNRESET:虚电路被远端复位。,17.6.7 recvfrom和sendto,简述:recevfrom/sendto类似于recev/send,一般情况下前者用于UDP,后者用于TCP。两者参数完全相同。recevfrom与recev差别是前者在获取数据的同时还可以获得该数据的原地址。,UDP,TCP,17.6.7 recvfrom和sendto(recvfrom),简述:

45、接收一个数据报并保存源地址。#include int recvfrom(SOCKET s,char FAR*buf,int len,int flags,struct sockaddr FAR*from,int FAR*fromlen);s:标识一个已连接套接口的描述字。buf:接收数据缓冲区。len:缓冲区长度。flags:调用操作方式。from:(可选)指针,指向装有源地址的缓冲区。fromlen:(可选)指针,指向from缓冲区长度值。,17.6.7 recvfrom和sendto(recvfrom),注释:本函数由于从(已连接)套接口上接收数据,并捕获数据发送源的地址。对于SOCK_ST

46、REAM类型的套接口,最多可接收缓冲区大小个数据。如果套接口被设置为线内接收带外数据(选项为SO_OOBINLINE),且有带外数据未读入,则返回带外数据。应用程序可通过调用ioctlsocket()的SOCATMARK命令来确定是否有带外数据待读入。对于SOCK_STREAM类型套接口,忽略from和fromlen参数。,17.6.7 recvfrom和sendto(recvfrom),注释:对于数据报类套接口,队列中第一个数据报中的数据被解包,但最多不超过缓冲区的大小。如果数据报大于缓冲区,那么缓冲区中只有数据报的前面部分,其他的数据都丢失了,并且recvfrom()函数返回WSAEMSG

47、SIZE错误。若from非零,且套接口为SOCK_DGRAM类型,则发送数据源的地址被复制到相应的sockaddr结构中。fromlen所指向的值初始化时为这个结构的大小,当调用返回时按实际地址所占的空间进行修改。,17.6.7 recvfrom和sendto(recvfrom),注释:如果没有数据待读,那么除非是非阻塞模式,不然的话套接口将一直等待数据的到来,此时将返回SOCKET_ERROR错误,错误代码是WSAEWOULDBLOCK。用select()或WSAAsynSelect()可以获知何时数据到达。如果套接口为SOCK_STREAM类型,并且远端“优雅”地中止了连接,那么recvf

48、rom()一个数据也不读取,立即返回。如果立即被强制中止,那么recv()将以WSAECONNRESET错误失败返回。,17.6.7 recvfrom和sendto(recvfrom),在套接口的所设选项之上,还可用标志位flag来影响函数的执行方式。也就是说,本函数的语义既取决于套接口选项,也取决于标志位参数。标志位可取下列值:,17.6.7 recvfrom和sendto(recvfrom),返回值:若无错误发生,recvfrom()返回读入的字节数。如果连接已中止,返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。,17

49、.6.7 recvfrom和sendto(recvfrom),错误代码:WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。WSAEFAULT:fromlen参数非法;from缓冲区大小无法装入端地址。WSAEINTR:阻塞进程被WSACancelBlockingCall()取消。WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。WSAEINVAL:套接口未用bind()进行捆绑。WSAENOTCONN:套接口未连接(仅适用于SOCK_STREAM类型)。

50、,17.6.7 recvfrom和sendto(recvfrom),错误代码:WSAENOTSOCK:描述字不是一个套接口。WSAEOPNOTSUPP:指定了MSG_OOB,但套接口不是SOCK_STREAM类型的。WSAESHUTDOWN:套接口已被关闭。当一个套接口以0或2的how参数调用shutdown()关闭后,无法再用recv()接收数据。WSAEWOULDBLOCK:套接口标识为非阻塞模式,但接收操作会产生阻塞。WSAEMSGSIZE:数据报太大无法全部装入缓冲区,故被剪切。WSAECONNABORTED:由于超时或其他原因,虚电路失效。WSAECONNRESET:远端强制中止了虚

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号