标准TCPIPsocket编程_第1页
标准TCPIPsocket编程_第2页
标准TCPIPsocket编程_第3页
标准TCPIPsocket编程_第4页
标准TCPIPsocket编程_第5页
已阅读5页,还剩101页未读 继续免费阅读

下载本文档

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

文档简介

1、标准TCP/IP编程接口 Socket标准TCP/IP编程接口 Socket 套接口概述地址与地址操作函数INET协议族地址结构sockaddr_inIPv4地址结构in_addr通用地址结构sockaddr地址操作函数端口字节序问题三种套接口类型和两种I/O模式套接口的类型I/O模式标准TCP/IP编程接口Socket基本套接口函数 WSAStartupsocket 创建套接字bind 绑定本机接口connect 建立连接listen 监听端口accept 接受连接recv,recvfrom 数据接收send,sendto 数据发送close,shutdown 关闭套接字WSACleanup

2、 Socket 函数在帮助链接套接口概述Berkeley sockets 接口在windows平台上的移植版本称为Winsock。最初的伯克利套接口API在windows平台上的移植版本是Winsock1.1,在它的基础上,微软又进一步提供了Winsock2.0从用户的角度来看,套接口是网络通信端点的一种抽象概念,为用户提供一种发送和接收数据的机制。是一种进程间通信的机制,适用于分布式环境。套接口概念及其编程原理字节顺序l大序在前:在起始地址存放整数的高序号字节l小序在前:在起始地址存放低整数的低序号字节字节顺序主机字节顺序l不同的机器主机字节顺序是不一样的,在windows操作系统中使用的是

3、小序在前小序在前的存储方式。网络字节顺序l为了保证数据的正确性,在网络通信协议中必须指定网络字节顺序。如果在网络中使用IP地址和端口号,按“互联网联网标准”的要求,指定的多字节值必须用“大序在前大序在前”的形式表示,一般称为“网络字节”顺序。在winsock中有一系列的函数可用于多字节的转换,把它们从主机字节的顺序转换成网络字节顺序,反之亦然。字节顺序转换htons()l“Host to Network Short” l2字节主机字节顺序转换为网络字节顺序htonl()l“Host to Network Long” l4字节主机字节顺序转换为网络字节顺序ntohs()l“Network to

4、Host Short” l2字节主机字节顺序转换为网络字节顺序ntohl()l“Network to Host Long” l4字节网络字节顺序转换为主机字节顺序INET协议地址结构sockaddr_in struct sockaddr_inShort sin_family;U_short sin_port;Struct in_addr sin_addr;Char sin_zero8; 地址族,一般填AF_INET16位IP端口32位IP地址8个字节的0填充,给结构体初始化清0的函数如下Void *memset(void *dest,int c,size_t count);所以是TCP/IPI

5、Pv4地址结构in_addr struct in_addr unsigned long s_addr; ;INET协议地址结构中的IP地址部分通用地址结构sockaddr struct sockaddru_short sa_family;char sa_data14; 一种是只为TCP/IP,另外是为了提供通用接口以服务多种网络协议开发的通用结构,但要提供足够的信息说明自己的协议,复杂!例如: Int connetct(socket s,const struct sockaddr FAR *name,int namelen) 对于程序员来说,很少直接使用这种通用地址结构。连接时不是struct

6、 sockadr_in*而是通用地址结构地址操作函数 3个常用的地址操作函数:将点分格式的IPv4地址字符串转化为in_addr地址结构适用的32位整数:unsigned long inet_addr(const char FAR *cp);将in_addr地址值转化为标准的点分IP地址字符串:char FAR *inet_ntoa(struct in_addr in);域名解析功能:struct hostent FAR *gethostbyname(const char FAR *name); 注意注意:在使用winsock函数之前,应用程序必须首先调用WSAStartup函数初始化ws2_

7、32.dll,而在应用结束后必须调用WSACleanup函数关闭。IPv4地址结构in_addr 假设你用 struct sockaddr_in ina,你想将 IP 地址 132.241.5.10 储存到其中。你要用的函数是 inet_addr(),转换 numbers-and-dots 格式的 IP 地址到 unsigned long。这个工作可以这样来做: lina.sin_addr.s_addr = inet_addr(132.241.5.10);inet_addr(132.241.5.10); 注意:inet_addr() 返回的地址已经是按照网络字节顺序的,你没有必要再去调用 ht

8、onl()。 如何按照 numbers-and-dots 格式打印呢? 在这个 时候,也许你要用函数 inet_ntoa() (ntoa 意思是 network to ascii) lprintf(%s,inet_ntoa(ina.sin_addr); 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_length;

9、 /* length of address */ char FAR * FAR * h_addr_list; /* list of addresses */ #define h_addr h_addr_list0 /* address, for backward compat */;端口0:不使用11023:知名端口10245000:可以被任意客户端程序使用可以被任意客户端程序使用500165535:为其他服务器程序预留三种套接口类型流套接口(SOCK_STREAM)l面向连接的TCP数据报套接口(SOCK_DGRAM)l无连接的UDP原始套接口(SOCK_RAW)l可以读写ICMP、IGMP

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

11、CK):便于使用非阻塞(NONBLOCK):效率较高默认情况下,Winsock函数都以阻塞模式工作面向连接的C/S网络通信程序工作流程图(TCP)无连接的C/S网络通信程序工作流程图(UDP)这个bind可以是隐式的。 基本套接口函数 例如:TCP服务器程序流程:初始化Winsock创建一个Socket绑定并监听本地的特定端口accept接收客户端的连接在accept操作返回的Socket上进行数据通信关闭Socket最后结束Winsock的使用 基本套接口函数WSAStartupSocketBindListenAcceptConnectrecv和sendrecvfrom和sendtoClos

12、esocketWSACleanup.1 WSAStartup 简述简述:#include int WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData );wVersionRequested:应用程序需要的最高版本,双字节数值型,高位字节指出副版本(修正)号,低位字节指明主版本号。lpWSAData:指向WSADATA数据结构的指针,用来接收Windows Sockets实现的信息。.1 WSAStartup 注释注释: WSAStartup()函数必须是应用程序或DLL调用的第一个Winsock函数。成功调用之后才能进一步的调用别的

13、Winsock函数。 它允许应用程序或DLL指明Windows Sockets API的版本号及获得特定Windows Sockets实现的细节。.1 WSAStartup 注释注释: WSAStartup() 的调用过程l一方面是初始化ws2_32.dll。l另一方面和Winsock库进行版本协商,只有要求的版本=系统支持的最低版本(下限)才成功。并且在wHighVersion中返回系统支持的最高版本,在wVersion中返回系统支持的高版本(上限)和wVersionRequested中的较小者。然后Winsock库就会假设应用程序将使用wVersion。如果WSDATA结构中的wVersi

14、on域对调用方来说不可接收, 要么去另一个Windows Sockets DLL中搜索,要么初始化失败。.1 WSAStartup 本协议允许Windows Sockets DLL和Windows Sockets应用程序共同支持一定范围的Windows Sockets版本。如果版本范围有重叠,应用程序就可以成功地使用Windows Sockets DLL。 后面的图表给出了WSAStartup()在不同的应用程序和Windows Sockets DLL版本中是如何工作的:.1 WSAStartup应用程序版本 DLL版本 wVersionRequested程序要求最高 wVersion程序要求

15、与系统最低的最小值wHighVersion系统最高 最终结果 1.11.1 1.1 1.1 1.1 use 1.11.0 1.11.0 1.11.01.0use 1.0 1.01.0 1.11.01.01.1use 1.01.1 1.0.1.1 1.11.1 1.1use 1.11.11.01.1 1.01.0失败1.0 1.11.0WSAVERNOTSUPPORTED1.0 1.11.0 1.11.1 1.11.1use 1.11.1.2.01.12.01.11.1use 1.12.01.12.0 1.1 1.1失败.1 WSAStartup 返回值返回值: 0:成功 否则返回错误代码 注意

16、通常依靠应用程序调用WSAGetLastError()机制获得的错误代码可能不完全,因为Windows Sockets DLL可能没有建立“上一错误”信息储存的客户数据区域。.1 WSAStartup错误代码错误代码:WSASYSNOTREADY:指出网络通信依赖的网络子系统还没有准备好。WSAVERNOTSUPPORTED:所需的Windows Sockets API的版本未由特定的Windows Sockets实现提供。WSAEINVAL:应用程序指出的Windows Sockets版本不被该DLL支持。.1 WSAStartup示例示例:#pragma comment(lib, “ ws

17、2_32.lib”)#include #include Int main (int arge,char*argv) WORD wVersionReq=MAKEWORD(0,1); /*希望使用1.0版本*/ WSAData wsaData; int ret=WSAStartup(wVersionReq,&wsaData) if(ret!=0) printf(“%dn,ret”) return 1; else printf(“High:%xUse:%xn”,wsaData.wHighVersion,wsaData.wVersion”); WSACleantup(); return 0; .2 s

18、ocket 功能功能:使用前创建一个新的套接字定义定义:SOCKET socket(int af, int type, int protocol);返回值:返回值:非负整数描述符表示成功,-1表示出错AfAf指定协议族,一般设为AF_INET,对应internet。Type有三种类型ProtocolProtocol指定所用的协议,在TCP或UDP编程的时候都取0。类型(type)SOCK_STREAMSOCK_DGRAMSOCK_RAM解释字节流套接口数据报套接口原始套接口af=AF_INET时选择的协议TCPUDPIPv4socket()-得到文件描述符!得到文件描述符!afl说明套接字使用

19、的协议簇,如果想建立一个TCP或UDP的套接字,此值设置成常量“AF_INET”。type l套接字的协议类型lSOCK_STREAM 类型还是 SOCK_DGRAM 类型。protocol l套接字使用的特定协议lIPPROTO_TCP和IPPROTO_UDPl也可设置为 “0”。系统会根据前两个参数的值自动确定一个协议字段的取值。.2 socket示例:SOCKET sock=socket(AF_INET, SOCK_STREAM, 0);SOCKET sock=socket(AF_INET, SOCK_DGREAM, 0);SOCKET sock=socket(AF_INET, SOCK

20、_RAW,IPPROTO_ICMP);例如:创建套接字(TCP)不成功就提示if (socket(AF_INET, SOCK_STREAM, 0) 0)fprintf(stderr,“socket creating errorn”);exit(1);.3 bind 简述:简述: 本函数将一本地的传输层地址与已经创建的套接口联系起来,一般来说,作为客户端程序,不用关心它的本地地址是什么,也就没有必要调用bind函数,系统会在通信前自动选择一个本地地址(10245000)。 但服务进程则必须绑定到一个为客户端所知的地址上。.3 bind #include int bind( SOCKET s, c

21、onst struct sockaddr FAR* name, int namelen);s:标识一未捆绑套接口的描述字name:赋予套接口的地址。sockaddr结构定义如下:struct sockaddr u_short sa_family; char sa_data14; ;namelen:name名字的长度.3 bind注释:注释: 本函数适用于未连接的数据报或流类套接口,在connect()或listen()调用前使用。当用socket()创建套接口后,它便存在于一个名字空间(地址族)中,但并未赋名。bind()函数通过给一个未命名套接口分配一个本地名字来为套接口建立本地捆绑(主机地

22、址/端口号)。 .3 bind注释:注释: 在Internet地址族中,一个名字包括几个组成部分,对于SOCK_DGREAM和SOCK_STREAM类套接口,名字由三部分组成:主机地址,协议号(显式设置为UDP和TCP)和用以区分应用的端口号。如果一个应用并不关心分配给它的地址,则可将Internet地址设置为INADDR_ANY,或将端口号置为0。如果Internet地址段为INADDR_ANY,则可使用任意网络接口;在有多种主机环境下可简化编程。如果端口号置为0,则WINDOWS套接口实现将给应用程序分配一个值在1024到5000之间的唯一的端口。应用程序可在bind()后用getsock

23、name()来获知所分配的地址,但必需注意的是,getsockname()只有在套接口连接成功后才会填写Internet地址,这是由于在多种主机环境下若干种Internet地址都是有效的。.3 bind 返回值:返回值: 如无错误发生,则bind()返回0。否则的话,将返回SOCKET_ERROR,应用程序可通过WSAGetLastError()获取相应错误代码。.3 bind错误代码:错误代码: WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。 WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。 WSAEADDRINUSE:

24、所定端口已在使用中(参见setoption()中的SO_REUSEADDR选项)。.3 bind错误代码:错误代码: WSAEFAULT:namelen参数太小(小于sockaddr结构的大小)。 WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。 WSAEAFNOSUPPORT:本协议不支持所指定的地址族。 WSAEINVAL:该套接口已与一个地址捆绑。 WSAENOBUFS:无足够可用缓冲区,连接过多。 WSAENOTSOCK:描述字不是一个套接口。 .3 bind示例:创建TCP,绑定IP和端口SOCKET sock=socket(AF_INET,SOCK_ST

25、REAM,0);Struct sockaddr_in local;Memset(&local,0,sizeof(local);local.sin_addr.s_addr=inet_addr(“202.119.9.199”);Local.sin_family=AF_INET;Local.sin_port=htons(9999);If(bind(sock,(struct sockaddr*)&local,sizeof(local)=SOCKET_ERROR) Printf(“Error:%dn”,WSAGetlastError(); WSACleanup(); Return 1; 注意事项loca

26、l.sin_port 和local.sin_addr.s_addr都是网络字节顺序。另外要注意到的事情是因系统的不同,包含的头文件也不尽相同。在处理自己的 IP 地址和/或端口的时候,有些工作是可以自动处理的。 llocal.sin_port = 0; /* choose an unused port at random */ local.sin_addr.s_addr = INADDR_ANY; /* use my IP address */ l通过将0赋给 local.sin_port,你告诉 bind() 自己选择合适的端口。同样, 将 local.sin_addr.s_addr 设置为

27、 INADDR_ANY,你告诉他自动填上他所运行的机器的 IP 地址。 bind() 在错误的时候依然是返回-1,并且设置全局变量 errno。 在你调用 bind() 的时候,你要小心的另一件事情是:不要采用小于1024的端口号。所有小于1024的端口号都被系统保留!你可以选择从1024到65535(如果他们没有被别的程序使用的话)。 你要注意的另外一件小事是:有时候你根本不需要调用他。如果你使用 connect() 来和远程机器通讯,你不要关心你的本地端口号(就象你在使用 telnet 的时候),你只要简单的调用 connect() 就够了,他会检查套接口是否绑定,如果没有,他会自己绑定一

28、个没有使用的本地端口。.3 bind 如果一个应用程序需要把端口捆绑到超过10245000范围的特定端口时,比如需要捆绑到任一保留端口,则可如下编程: SOCKADDR_IN sin; SOCKET s; u_short alport=IPPORT_RESERVED; sin.sin_family=AF_INET; sin.sin_addr.s_addr=0; for (;) sin.sin_port=htons(alport); if (bind(s,(LPSOCKADDR)&sin, sizeof(sin)=0) /* it worked */ if (GetLastError()!=WS

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

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

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

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

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

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

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

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

37、Socket,(struct sockaddr *)&ServerSocketAddr,&addrlen); .6 connect简述简述:客户端建立与一个服务端的连接。#include int connect( SOCKET s, const struct sockaddr FAR* name, int namelen);s:标识一个未连接套接口的描述字。name:欲进行连接的端口名。namelen:名字长度。.6 connect注释:注释: s参数指定一个未连接的数据报或流类套接口。如套接口未被捆绑,则系统赋给本地关联一个唯一的值,且设置套接口为已捆绑。 对于流类套接口(SOCK_STRE

38、AM类型),函数会引起三次TCP握手,一旦套接口调用成功返回,它就能收发数据了。 对于数据报类套接口(SOCK_DGRAM类型),则设置成一个缺省的目的地址,并用它来进行后续的send()与recv()调用。.6 connect 返回值:返回值: 若无错误发生,则connect()返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。对阻塞套接口而言,若返回值为SOCKET_ERROR则应用程序调用WSAGetLsatError()。如果它指出错误代码为WSAEWOULDBLOCK,则应用程序可以: 1.用select(),通过检

39、查套接口是否可写,来确定连接请求是否完成。 2.如果您的应用程序使用基于消息的WSAAsynSelect()来表示对连接事件的兴趣,则当连接操作完成后,您会收到一个FD_CONNECT消息。.6 connect错误代码错误代码: WSAENOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。 WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。 WSAEADDRINUSE:所指的地址已在使用中。 WSAEINTR:通过一个WSACancelBlockingCall()来取消一个(阻塞的)调用。 WSAEINPROGRESS:一个阻塞的WIN

40、DOWS套接口调用正在运行中。 WSAEADDRNOTAVAIL:在本地机器上找不到所指的地址。 WSAENOTSUPPORT:所指族中地址无法与本套接口一起使用。 WSAECONNREFUSED:连接尝试被强制拒绝。 WSAEDESTADDREQ:需要目的地址。.6 connect错误代码错误代码: WSAEFAULT:namelen参数不正确。 WSAEINVAL:套接口没有准备好与一地址捆绑。 WSAEISCONN:套接口早已连接。 WSAEMFILE:无多余文件描述字。 WSAENETUNREACH:当前无法从本主机访问网络。 WSAENOBUFS:无可用缓冲区。套接口未被连接。 WS

41、AENOTSOCK:描述字不是一个套接口。 WSAETIMEOUT:超时时间到。 WSAEWOULDBLOCK:套接口设置为非阻塞方式且连接不能立即建立。可用select() 调用对套接口写,因为select()时会进行连接。.6 connect下面是一个例子: struct sockaddr_in daddr; memset(void *)&daddr,0,sizeof(daddr); daddr.sin_family=AF_INET; daddr.sin_port=htons(8888); daddr.sin_addr.s_addr=inet_addr(133.197.22.4); con

42、nect(ClientSocket,(struct sockaddr *)&daddr,sizeof(daddr); .7 recv和send( recv )功能功能:从一个套接口接收数据可以是面向连接的,必须是已经连接的。也可以是无连接的,但必须是已经绑定的。.7 recv和send( recv )简述简述:从一个套接口接收数据。 #include int recv( SOCKET s, char FAR* buf, int len, int flags); s:一个标识已连接套接口的描述字。 buf:用于接收数据的缓冲区。 len:缓冲区长度。 flags:指定调用方式。.7 recv和s

43、end( recv )注释:注释: 本函数用于已连接的数据报或流式套接口s进行数据的接收。 对SOCK_STREAM类型的套接口来说,本函数将返回所有可用的信息,最大可达缓冲区的大小。如果套接口被设置为线内接收带外数据(选项为SO_OOBINLINE),且有带外数据未读入,则返回带外数据。应用程序可通过调用ioctlsocket()的SOCATMARK命令来确定是否有带外数据待读入。.7 recv和send( recv )注释:注释: 对于数据报类套接口,队列中第一个数据报中的数据被解包,但最多不超过缓冲区的大小。如果数据报大于缓冲区,那么缓冲区中只有数据报的前面部分,其他的数据都丢失了,并且

44、recv()函数返回WSAEMSGSIZE错误。如果没有数据待读,那么除非是非阻塞模式,不然的话套接口将一直等待数据的到来,此时将返回SOCKET_ERROR错误,错误代码是WSAEWOULDBLOCK。用select()或WSAAsynSelect()可以获知何时数据到达。.7 recv和send( recv ) 如果套接口为SOCK_STREAM类型,并且远端“正常”地中止了连接,那么recv()一个数据也不读取,立即返回。如果被“强制”中止,那么recv()将以WSAECONNRESET错误失败返回。 在套接口的所设选项之上,还可用标志位flag来影响函数的执行方式。也就是说,本函数的语

45、义既取决于套接口选项,也取决于标志位参数。标志位可取下列值:值 意义MSG_PEEK 查看当前数据。数据将被复制到缓冲区中,但并不从输入队列中删除。 MSG_OOB 处理带外数据 .7 recv和send( recv )返回值返回值: 若无错误发生,recv()返回读入的字节数。如果连接已中止,返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。 .7 recv和send( recv )错误代码:错误代码: WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。 WSAENETDOWN:

46、WINDOWS套接口实现检测到网络子系统失效。 WSAENOTCONN:套接口未连接。 WSAEINTR:阻塞进程被WSACancelBlockingCall()取消。 WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。 WSAENOTSOCK:描述字不是一个套接口。 WSAEOPNOTSUPP:指定了MSG_OOB,但套接口不是SOCK_STREAM类型的。 WSAESHUTDOWN:套接口已被关闭。当一个套接口以0或2的how参数调用shutdown()关闭后,无法再用recv()接收数据。.7 recv和send( recv )错误代码:错误代码: WSAEWO

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

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

49、方式,否则send()将阻塞。对于非阻塞SOCK_STREAM类型的套接口,实际写的数据数目可能在1到所需大小之间,其值取决于本地和远端主机的缓冲区大小。可用select()调用来确定何时能够进一步发送数据。.7 recv和send( send ) 在相关套接口的选项之上,还可通过标志位flag来影响函数的执行方式。也就是说,本函数的语义既取决于套接口的选项也取决于标志位。后者由以下一些值组成:值 意义MSG_DONTROUTE 指明数据不选径。一个WINDOWS套接口供应商可以忽略此标志 MSG_OOB 发送带外数据(仅适用于SO_STREAM;) .7 recv和send( send )返

50、回值:返回值: 若无错误发生,send()返回所发送数据的总数(请注意这个数字可能小于len中所规定的大小)。 否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。.7 recv和send( send )错误代码:错误代码: WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。 WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。 WSAEACESS:要求地址为广播地址,但相关标志未能正确设置。 WSAEINTR:通过一个WSACancelBlockingCall()来取消一

51、个(阻塞的)调用。 WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。 WSAEFAULT:buf参数不在用户地址空间中的有效位置。 WSAENETRESET:由于WINDOWS套接口实现放弃了连接,故该连接必需被复位。 WSAENOBUFS:WINDOWS套接口实现报告一个缓冲区死锁。 WSAENOTCONN:套接口未被连接。 WSAENOTSOCK:描述字不是一个套接口。.7 recv和send( send )错误代码:错误代码: WSAEOPNOTSUPP:已设置了MSG_OOB,但套接口非SOCK_STREAM类型。 WSAESHUTDOWN:套接口已被关闭。

52、一个套接口以1或2的how参数调用shutdown()关闭后,无法再用sned()函数。 WSAEWOULDBLOCK: WSAEMSGSIZE:套接口为SOCK_DGRAM类型,且数据报大于WINDOWS套接口实现所支持的最大值。 WSAEINVAL:套接口未用bind()捆绑。 WSAECONNABORTED:由于超时或其他原因引起虚电路的中断。 WSAECONNRESET:虚电路被远端复位。.7 recvfrom和sendto简述简述: recevfrom/sendto类似于recev/send,一般情况下前者用于UDP,后者用于TCP。两者参数完全相同。 recevfrom与recev

53、差别是前者在获取数据的同时还可以获得该数据的原地址。UDPTCP.7 recvfrom和sendto(recvfrom)简述简述:接收一个数据报并保存源地址。#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缓冲区长度

54、值。.7 recvfrom和sendto(recvfrom) 注释注释: 本函数由于从(已连接)套接口上接收数据,并捕获数据发送源的地址。 对于SOCK_STREAM类型的套接口,最多可接收缓冲区大小个数据。如果套接口被设置为线内接收带外数据(选项为SO_OOBINLINE),且有带外数据未读入,则返回带外数据。应用程序可通过调用ioctlsocket()的SOCATMARK命令来确定是否有带外数据待读入。对于SOCK_STREAM类型套接口,忽略from和fromlen参数。.7 recvfrom和sendto(recvfrom) 注释注释: 对于数据报类套接口,队列中第一个数据报中的数据被

55、解包,但最多不超过缓冲区的大小。如果数据报大于缓冲区,那么缓冲区中只有数据报的前面部分,其他的数据都丢失了,并且recvfrom()函数返回WSAEMSGSIZE错误。 若from非零,且套接口为SOCK_DGRAM类型,则发送数据源的地址被复制到相应的sockaddr结构中。fromlen所指向的值初始化时为这个结构的大小,当调用返回时按实际地址所占的空间进行修改。.7 recvfrom和sendto(recvfrom)注释注释: 如果没有数据待读,那么除非是非阻塞模式,不然的话套接口将一直等待数据的到来,此时将返回SOCKET_ERROR错误,错误代码是WSAEWOULDBLOCK。用se

56、lect()或WSAAsynSelect()可以获知何时数据到达。 如果套接口为SOCK_STREAM类型,并且远端“优雅”地中止了连接,那么recvfrom()一个数据也不读取,立即返回。如果立即被强制中止,那么recv()将以WSAECONNRESET错误失败返回。.7 recvfrom和sendto(recvfrom)值 意义MSG_PEEK 查看当前数据。数据将被复制到缓冲区中,但并不从输入队列中删除 MSG_OOB 处理带外数据 在套接口的所设选项之上,还可用标志位flag来影响函数的执行方式。也就是说,本函数的语义既取决于套接口选项,也取决于标志位参数。标志位可取下列值:.7 re

57、cvfrom和sendto(recvfrom)返回值返回值: 若无错误发生,recvfrom()返回读入的字节数。如果连接已中止,返回0。否则的话,返回SOCKET_ERROR错误, 应用程序可通过WSAGetLastError()获取相应错误代码。.7 recvfrom和sendto(recvfrom) 错误代码错误代码: WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。 WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。 WSAEFAULT:fromlen参数非法;from缓冲区大小无法装入端地址。 WSAEINTR:阻塞

58、进程被WSACancelBlockingCall()取消。 WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。 WSAEINVAL:套接口未用bind()进行捆绑。 WSAENOTCONN:套接口未连接(仅适用于SOCK_STREAM类型)。.7 recvfrom和sendto(recvfrom) 错误代码错误代码: WSAENOTSOCK:描述字不是一个套接口。 WSAEOPNOTSUPP:指定了MSG_OOB,但套接口不是SOCK_STREAM类型的。 WSAESHUTDOWN:套接口已被关闭。当一个套接口以0或2的how参数调用shutdown()关闭后,无法再

59、用recv()接收数据。 WSAEWOULDBLOCK:套接口标识为非阻塞模式,但接收操作会产生阻塞。 WSAEMSGSIZE:数据报太大无法全部装入缓冲区,故被剪切。 WSAECONNABORTED:由于超时或其他原因,虚电路失效。 WSAECONNRESET:远端强制中止了虚电路。.7 recvfrom和sendto(sendto)简述简述:向一指定目的地发送数据。 #include int sendto( SOCKET s, const char FAR* buf, int len, int flags, const struct sockaddr FAR* to, int tolen)

60、; s:一个标识套接口的描述字。 buf:包含待发送数据的缓冲区。 len:buf缓冲区中数据的长度。 flags:调用方式标志位。 to:(可选)指针,指向目的套接口的地址。 tolen:to所指地址的长度。.7 recvfrom和sendto(sendto)注释注释: sendto()适用于已连接的数据报或流式套接口发送数据。对于数据报类套接口,必需注意发送数据长度不应超过通讯子网的IP包最大长度。IP包最大长度在WSAStartup()调用返回的WSAData的iMaxUdpDg元素中。如果数据太长无法自动通过下层协议,则返回WSAEMSGSIZE错误,数据不会被发送。.7 recvfr

温馨提示

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

评论

0/150

提交评论