技术文章 > Windows Socket API 使用经验

Windows Socket API 使用经验

2018-09-22 16:02

文档管理软件,文档管理系统,知识管理系统,档案管理系统的技术资料:

本文是我在进行MS-Windows、HP-Unix网络编程的实践过程中总结出来的一些经验,仅供大家参考。本文所谈到的Socket函数如果没有特别说明,都是指的Windows Socket API。
一、WSAStartup函数
int WSAStartup(
WORD wVersionRequested,
LPWSADATA lpWSAData
);
使用Socket的程序在使用Socket之前必须调用WSAStartup函数。该函数的第一个参数指明程序请求使用的Socket版本,其中高位字节指明副版本、低位字节指明主版本;操作系统利用第二个参数返回请求的Socket的版本信息。当一个应用程序调用WSAStartup函数时,操作系统根据请求的Socket版本来搜索相应的Socket库,然后绑定找到的Socket库到该应用程序中。以后应用程序就可以调用所请求的Socket库中的其它Socket函数了。该函数执行成功后返回0。
例:假如一个程序要使用2.1版本的Socket,那么程序代码如下
wVersionRequested = MAKEWORD( 2, 1 );
err = WSAStartup( wVersionRequested, &wsaData );
二、WSACleanup函数
int WSACleanup (void);
应用程序在完成对请求的Socket库的使用后,要调用WSACleanup函数来解除与Socket库的绑定并且释放Socket库所占用的系统资源。
三、socket函数
SOCKET socket(
int af,
int type,
int protocol
);
应用程序调用socket函数来创建一个能够进行网络通信的套接字。第一个参数指定应用程序使用的通信协议的协议族,对于TCP/IP协议族,该参数置PF_INET;第二个参数指定要创建的套接字类型,流套接字类型为SOCK_STREAM、数据报套接字类型为SOCK_DGRAM;第三个参数指定应用程序所使用的通信协议。该函数如果调用成功就返回新创建的套接字的描述符,如果失败就返回INVALID_SOCKET。套接字描述符是一个整数类型的值。每个进程的进程空间里都有一个套接字描述符表,该表中存放着套接字描述符和套接字数据结构的对应关系。该表中有一个字段存放新创建的套接字的描述符,另一个字段存放套接字数据结构的地址,因此根据套接字描述符就可以找到其对应的套接字数据结构。每个进程在自己的进程空间里都有一个套接字描述符表但是套接字数据结构都是在操作系统的内核缓冲里。下面是一个创建流套接字的例子:
struct protoent *ppe;
ppe=getprotobyname(“tcp“);
SOCKET ListenSocket=socket(PF_INET,SOCK_STREAM,ppe->p_proto);
四、closesocket函数
int closesocket(
SOCKET s
);
closesocket函数用来关闭一个描述符为s套接字。由于每个进程中都有一个套接字描述符表,表中的每个套接字描述符都对应了一个位于操作系统缓冲区中的套接字数据结构,因此有可能有几个套接字描述符指向同一个套接字数据结构。套接字数据结构中专门有一个字段存放该结构的被引用次数,即有多少个套接字描述符指向该结构。当调用closesocket函数时,操作系统先检查套接字数据结构中的该字段的值,如果为1,就表明只有一个套接字描述符指向它,因此操作系统就先把s在套接字描述符表中对应的那条表项清除,并且释放s对应的套接字数据结构;如果该字段大于1,那么操作系统仅仅清除s在套接字描述符表中的对应表项,并且把s对应的套接字数据结构的引用次数减1。
closesocket函数如果执行成功就返回0,否则返回SOCKET_ERROR。
五、send函数
int send(
SOCKET s,
const char FAR *buf,
int len,
int flags
);
不论是客户还是服务器应用程序都用send函数来向TCP连接的另一端发送数据。客户程序一般用send函数向服务器发送请求,而服务器则通常用send函数来向客户程序发送应答。该函数的第一个参数指定发送端套接字描述符;第二个参数指明一个存放应用程序要发送数据的缓冲区;第三个参数指明实际要发送的数据的字节数;第四个参数一般置0。这里只描述同步Socket的send函数的执行流程。当调用该函数时,send先比较待发送数据的长度len和套接字s的发送缓冲区的长度,如果len大于s的发送缓冲区的长度,该函数返回SOCKET_ERROR;如果len小于或者等于s的发送缓冲区的长度,那么send先检查协议是否正在发送s的发送缓冲中的数据,如果是就等待协议把数据发送完,如果协议还没有开始发送s的发送缓冲中的数据或者s的发送缓冲中没有数据,那么send就比较s的发送缓冲区的剩余空间和len,如果len大于剩余空间大小send就一直等待协议把s的发送缓冲中的数据发送完,如果len小于剩余空间大小send就仅仅把buf中的数据copy到剩余空间里(注意并不是send把s的发送缓冲中的数据传到连接的另一端的,而是协议传的,send仅仅是把buf中的数据copy到s的发送缓冲区的剩余空间里)。如果send函数copy数据成功,就返回实际copy的字节数,如果send在copy数据时出现错误,那么send就返回SOCKET_ERROR;如果send在等待协议传送数据时网络断开的话,那么send函数也返回SOCKET_ERROR。要注意send函数把buf中的数据成功copy到s的发送缓冲的剩余空间里后它就返回了,但是此时这些数据并不一定马上被传到连接的另一端。如果协议在后续的传送过程中出现网络错误的话,那么下一个Socket函数就会返回SOCKET_ERROR。(每一个除send外的Socket函数在执行的最开始总要先等待套接字的发送缓冲中的数据被协议传送完毕才能继续,如果在等待时出现网络错误,那么该Socket函数就返回SOCKET_ERROR)
注意:在Unix系统下,如果send在等待协议传送数据时网络断开的话,调用send的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。
六、recv函数
int recv(
SOCKET s,
char FAR *buf,
int len,
int flags
);
不论是客户还是服务器应用程序都用recv函数从TCP连接的另一端接收数据。该函数的第一个参数指定接收端套接字描述符;第二个参数指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据;第三个参数指明buf的长度;第四个参数一般置0。这里只描述同步Socket的recv函数的执行流程。当应用程序调用recv函数时,recv先等待s的发送缓冲中的数据被协议传送完毕,如果协议在传送s的发送缓冲中的数据时出现网络错误,那么recv函数返回SOCKET_ERROR,如果s的发送缓冲中没有数据或者数据被协议成功发送完毕后,recv先检查套接字s的接收缓冲区,如果s接收缓冲区中没有数据或者协议正在接收数据,那么recv就一直等待,只到协议把数据接收完毕。当协议把数据接收完毕,recv函数就把s的接收缓冲中的数据copy到buf中(注意协议接收到的数据可能大于buf的长度,所以在这种情况下要调用几次recv函数才能把s的接收缓冲中的数据copy完。recv函数仅仅是copy数据,真正的接收数据是协议来完成的),recv函数返回其实际copy的字节数。如果recv在copy时出错,那么它返回SOCKET_ERROR;如果recv函数在等待协议接收数据时网络中断了,那么它返回0。
注意:在Unix系统下,如果recv函数在等待协议接收数据时网络断开了,那么调用recv的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。
七、bind函数
int bind(
SOCKET s,
const struct sockaddr FAR *name,
int namelen
);
当创建了一个Socket以后,套接字数据结构中有一个默认的IP地址和默认的端口号。一个服务程序必须调用bind函数来给其绑定一个IP地址和一个特定的端口号。客户程序一般不必调用bind函数来为其Socket绑定IP地址和断口号。该函数的第一个参数指定待绑定的Socket描述符;第二个参数指定一个sockaddr结构,该结构是这样定义的:
struct sockaddr {
u_short sa_family;
char sa_data[14];
};
sa_family指定地址族,对于TCP/IP协议族的套接字,给其置AF_INET。当对TCP/IP协议族的套接字进行绑定时,我们通常使用另一个地址结构:
struct sockaddr_in {
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
其中sin_family置AF_INET;sin_port指明端口号;sin_addr结构体中只有一个唯一的字段s_addr,表示IP地址,该字段是一个整数,一般用函数inet_addr()把字符串形式的IP地址转换成unsigned long型的整数值后再置给s_addr。有的服务器是多宿主机,至少有两个网卡,那么运行在这样的服务器上的服务程序在为其Socket绑定IP地址时可以把htonl(INADDR_ANY)置给s_addr,这样做的好处是不论哪个网段上的客户程序都能与该服务程序通信;如果只给运行在多宿主机上的服务程序的Socket绑定一个固定的IP地址,那么就只有与该IP地址处于同一个网段上的客户程序才能与该服务程序通信。我们用0来填充sin_zero数组,目的是让sockaddr_in结构的大小与sockaddr结构的大小一致。下面是一个bind函数调用的例子:
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(8888);
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(ListenSocket,(struct sockaddr *)&saddr,sizeof(saddr));
八、listen函数
int listen( SOCKET s, int backlog );
服务程序可以调用listen函数使其流套接字s处于监听状态。处于监听状态的流套接字s将维护一个客户连接请求队列,该队列最多容纳backlog个客户连接请求。假如该函数执行成功,则返回0;如果执行失败,则返回SOCKET_ERROR。
九、accept函数
SOCKET accept(
SOCKET s,
struct sockaddr FAR *addr,
int FAR *addrlen
);
服务程序调用accept函数从处于监听状态的流套接字s的客户连接请求队列中取出排在最前的一个客户请求,并且创建一个新的套接字来与客户套接字创建连接通道,如果连接成功,就返回新创建的套接字的描述符,以后与客户套接字交换数据的是新创建的套接字;如果失败就返回INVALID_SOCKET。该函数的第一个参数指定处于监听状态的流套接字;操作系统利用第二个参数来返回新创建的套接字的地址结构;操作系统利用第三个参数来返回新创建的套接字的地址结构的长度。下面是一个调用accept的例子:
struct sockaddr_in ServerSocketAddr;
int addrlen;
addrlen=sizeof(ServerSocketAddr);
ServerSocket=accept(ListenSocket,(struct sockaddr *)&ServerSocketAddr,&addrlen);
十、connect函数
int connect(
SOCKET s,
const struct sockaddr FAR *name,
int namelen
);
客户程序调用connect函数来使客户Socket s与监听于name所指定的计算机的特定端口上的服务Socket进行连接。如果连接成功,connect返回0;如果失败则返回SOCKET_ERROR。下面是一个例子:
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“);
connect(ClientSocket,(struct sockaddr *)&daddr,sizeof(daddr));
Winsock API 函数大全 2
Submitted by 秋衫客 on 2005, September 1, 5:18 PM
本系统(WinKing)提供之 Windows Sockets API 介面乃是依照 1993年1月20日公布之 WINSOCK 第1.1版(如附录)中所定义之函式 (routine); 包括了30个Berkeley Software Distribution (BSD) 的函式以及16个符合 Windows Message-driven 特性的函式。
BSD 函式包括:
accept() bind() closesocket() connect()
getpeername() getsockname() getsockopt() htonl()
htons() inet_addr() inet_ntoa() ioctlsocket()
listen() ntohl() ntohs() recv()
recvfrom() select() send() sendto()
setsockopt() shutdown() socket() gethostname()
gethostbyaddr() gethostbyname()
getprotobyname() getprotobynumber()
getservbyname() getservbyport()
Microsoft Windows-specific Extensions 函式包括:
WSAAsyncGetHostByAddr() WSAAsyncGetHostByName()
WSAAsyncGetProtoByName() WSAAsyncGetProtoByNumber()
WSAAsyncGetServByName() WSAAsyncGetServByPort()
WSAAsyncSelect() WSACancelAsyncRequest()
WSACancelBlockingCall() WSACleanup()
WSAGetLastError() WSAIsBlocking()
WSASetBlockingHook() WSASetLastError()
WSAStartup() WSAUnhookBlockingHook()
这些 API 介面适用於 Internet Protocol Suite (IPS,通常称之为 TCP/IP),
支援 Stream (TCP) 及 Datagram (UDP) Socket。
Stream (TCP) Socket 提供「双向」、「可靠」、「有次序」、「不重覆」之资料传送。
Datagram (UDP) Socket 则提供「双向」之沟通,但没有「可靠」、「有次序」、「不重覆」等之保证; 所以使用者可能会收到无次序、重覆之资料,甚至资料在传输过程中也可能会遗漏。
[Blocking 与 Non-blocking 模式]
Blocking 模式:使用者呼叫此一模式之函式时,会进入此函式之内部,直到条件或资料完全符合时再回到呼叫点。
Non-blocking 模式:使用者呼叫此一模式之函式时,进入此函式之内部,依当时之条件或资料做适当之回覆,并不会停留在函式之内部到条件或资料完全符合後才回应。
使用者必需注意的是,WINSOCK 定义之 Blocking 模式与一般 Unix 的不太相同。WINSOCK定义允许应用程式在呼叫 Blocking 函式的同时,依旧能够处理其它讯息 (Messages),包括Keyboard 及 Mouse 的事件;但是此时应用程式除了能用 WSACancelBlockingCall() 函式来取消原先之 locking 动作或用WSAIsBlocking() 函式来检查目前是否有 Blocking 动作仍在进行外,不可以」在原先呼叫之Blocking 函式完成前再呼叫其它的 Socket 函式,不然後者会失败且产生WSAINPROGRESS 的错误。
使用者呼叫 WSACancelBlockingCall()函式所取消的 Blocking 动作若不是accept() 或者 select()的话,那麽之後唯一可呼叫的 Socket 函式只有closesocket(),因为取消一个 Socket 的Blocking 动作会使其变成未定(Indeterminate) 状态。
[Async (非同步) 模式]
使用者呼叫此一模式的函式时,并不会马上得到要求的资料;而是当要求的动作完成後,系统再透过另一种方式来通知呼叫者。其好处是使用者不需等到答覆後才可以再做其它的动作或要求。
WINSOCK定义的 Async 模式是以「PostMessage」的方式告知使用者其要求已经完成;所以在呼叫此类函式时,必须告知 Windows Sockets DLL一些资讯,包括接受讯息的视窗 handle及讯息编号等。
[函式概说]
[BSD Socket 程式库]
(1) accept():接受某一Socket的连接要求,以完成 Stream Socket 的连接。
格 式: SOCKET PASCAL FAR accept( SCOKET s,struct sockaddr FAR *addr,int FAR *addrlen );
参 数: s Socket的识别码 addr 存放来连接的彼端的位址 addrlen addr的长度
传回值: 成功 - 新的Socket识别码 失败 - INVALID_SOCKET (呼叫 WSAGetLastError() 可得知原因)
说明: Server 端之应用程式呼叫此一函式来接受 Client 端要求之Socket 连接动作;如果Server 端之 Socket 是为 Blocking 模式,且没有人要求连接动作,那麽此一函式会Block 函式马上回覆错误。accept() 函式的答覆值为一新的 Socket,此 Socket 不可再用来接受其它的连接要求;但是原先之 Socket 仍可接受其他人的连接要求。
(2) bind():指定 Socket 的 Local 位址 (Address)。
格 式: int PASCAL FAR bind( SOCKET s,const struct sockaddr FAR *name,int namelen );
参 数: s Socket的识别码 name Socket的位址值,其格式为
struct sockaddr
{
u_short sa_family;
char sa_data[14];
};
namelen name的长度
传回值: 成功 - 0
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 此一函式是指定 Local 位址及 Port 给某一未定名之 Socket。 使用者若不在意位址或 Port 的值,那麽他可以设定位址为 INADDR_ANY,及Port 为 0;那麽Windows Sockets 会自动将其设定适当之位址及 Port(1024 到 5000之间的值),使用者可以在此 Socket 真正连接完成後,呼叫 getsockname() 来获知其被设定的值。
(3) closesocket():关闭某一Socket。
格 式: int PASCAL FAR closesocket( SOCKET s );
参 数: s Socket 的识别码
传回值: 成功 - 0
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 此一函式是用来关闭某一 Socket。
若是使用者原先对要关闭之 Socket 设定 SO_DONTLINGER,则在呼叫此一函式後,会马上回覆,但是此一 Sokcet 尚未传送完毕的资料会继续送完後才关闭。
若是使用者原先设定此 Socket 为 SO_LINGER,则有两种情况:
(a) Timeout 设为 0 的话,此一 Socket 马上重新设定 (reset),未传完或未收到的资料全部遗失。
(b) Timeout 不为 0 的话,则会将资料送完,或是等到 Timeout 发生後才关闭。
(4) connect():要求连接某一Socket到指定的对方。
格 式: int PASCAL FAR connect( SOCKET s,const struct sockaddr FAR *name,int namelen );
参 数: s Socket 的识别码
name 此 Socket 想要连接的对方位址
namelen name的长度
传回值:成功 - 0
失败 - SOCKET_ERROR (呼叫WSAGetLastError()可得知原因)
说明: 此函式用来向对方要求建立连接。若是指定的对方位址为 0 的话,会传回错误值。当连接建立完成後,使用者即可利用此一 Socket 来做传送或接收资料之用了。
(5) getpeername():获取已连接成功之 Socket 的对方位址。
格 式: int PASCAL FAR getpeername( SOCKET s,struct sockaddr FAR *name,int FAR *namelen );
参 数: s Socket 的识别码
name 此 Socket 连接的对方位址
namelen name 的长度
传回值: 成功 - 0
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 此函式可用来取得已连接成功的 Socket 的彼端之位址资料。
(6) getsockname():获取 Socket 的 Local 位址资料。
格式: int PASCAL FAR getsockname( SOCKET s,struct sockaddr FAR *name,int FAR *namelen );
参数: s Socket 的识别码
name 此 Socket 的 Local 位址
namelen name 的长度
传回值: 成功 - 0
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 此函式是用来取得已设定位址或已连接之 Socket 的本端位址资料。若是此 Socket 被设定为 INADDR_ANY,则需等真正建立连接成功後才会传回正确的位址。
(7) getsockopt():要求某一 Socket 目前状态设定的资料。
格式: int PASCAL FAR getsockopt( SOCKET s,int level,int optname,char FAR *optval,int FAR *optlen );
参数: s= Socket的识别码,level=选项设定的,level=optname 选项名称,optval=选项的设定值,optlen=选项设定值的长度
传回值: 成功 - 0
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 此函式用来获取目前 Socket的某些状态设定值。 WINSOCK 提供之 level 只有 SOL_SOCKET 及 IPPROTO_TCP optname则有以下 之选择:(参见WINSOCK 第 29、30 页之定义)
Value Type
-----------------------------------------------
SO_ACCEPTCONN BOOL
SO_BROADCAST BOOL
*SO_DEBUG BOOL
SO_DONTLINGER BOOL
*SO_DONTROUTE BOOL
*SO_ERROR int
*SO_KEEPALIVE BOOL
SO_LINGER struct linger FAR*
SO_OOBINLINE BOOL
*SO_RCVBUF int
SO_REUSEADDR BOOL
*SO_SNDBUF int
SO_TYPE int
TCP_NODELAY BOOL
(* 表示暂不提供此功能选项)
(8) htonl():将一 32 位元 u_long 的值由 host 的排列方式转换成network 的排列方式。
格式: u_long PASCAL FAR htonl( u_long hostlong );
参数: hostlong 一个 32 位元 host 排列方式的数目
传回值: 一个 32 位元 network 排列方式的数目
说明: 因为 network 的排列方式与 host 的排列方式可能不同,所以我们需要此一函式来做转换。
(9) htons():将一 16 位元u_short 的值由 host 的排列方式转换成network 的排列方式。
格 式: u_short PASCAL FAR htons( u_short hostshort );
参 数: hostshort 一个 16 位元 host 排列方式的数目
传回值: 一个 16 位元 network 排列方式的数目
说明: 因为 network 的排列方式与 host 的排列方式可能不同,所以我们需要此一函式来做转换。
(10) inet_addr():将字串格式的位址转换成 32 位元 unsigned long 的格式。
格式: unsigned long PASCAL FAR inet_addr( const char FAR *cp );
参数: cp 一个代表位址的「点格式」(dotted) 字串
传回值: 成功 - 一个代表 Internet 位址的 unsigned long
失败 - INADDR_NONE
说明: 此函式将一「点格式」的位址字串转换成适用之Intenet位址。
「点格式」字串可为以下四种方式之任一:
(i) a.b.c.d (ii) a.b.c (iii) a.b (iv) a
本系统(WinKing)提供之 Windows Sockets API 介面乃是依照 1993年1月20日公布之 WINSOCK 第1.1版(如附录)中所定义之函式 (routine); 包括了30个Berkeley Software Distribution (BSD) 的函式以及16个符合 Windows Message-driven 特性的函式。
(11) inet_ntoa():将一网路位址转换成「点格式」字串。
格式: char FAR * PASCAL FAR inet_ntoa( struct in_addr in );
参数: in 一个代表 Internet 位址的结构
传回值: 成功 - 一个代表位址的「点格式」(dotted) 字串
失败 - NULL
说明: 此函式将一 Internet 位址转换成「a.b.c.d」字串格式。
(12) ioctlsocket():控制 Socket 的模式。
格式: int PASCAL FAR ioctlsocket( SOCKET s, long cmd, u_long FAR *argP );
参数: s Socket 的识别码,cmd 指令名称,argP 指向 cmd 参数的指标
传回值: 成功 - 0
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 此函式用来获取或设定 Socket 的运作参数。其所提供的指令有:
FIONBIO -- 开关 non-blocking 模式
FIONREAD -- 自 Socket 一次可读取的资料量
SIOCATMARK -- OOB 资料是否已被读取完 (*暂不提供此功能)
(13) listen():设定 Socket 为监听状态,准备被连接。
格 式: int PASCAL FAR listen( SOCKET s, int backlog );
参 数: s Socket 的识别码,backlog 未真正完成连接前(尚未呼叫 accept() 前)彼端的连接要求的最大个数
传回值: 成功 - 0
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 使用者可利用此函式来设定 Socket 进入监听状态,并设定最多可有多少个在未真正完成连接前的彼端的连接要求。(目前最大值限制为 5, 最小值为1)
(14) ntohl():将一 32 位元 u_long 的值由 network 排列方式转换成host 排列方式。
格式: u_long PASCAL FAR ntohl( u_long netlong );
参数: netlong 一个 32 位元 network 排列方式的数目
传回值: 一个 32 位元 host 排列方式的数目
说明: 因为 network 的排列方式与 host 的排列方式可能不同,所以我们需要此一函式来做转换。
(15) ntohs():将一 16 位元 u_short 的值由 network 排列方式转换成host 排列方式。
格式: u_short PASCAL FAR ntohs( u_short netshort );
参数: netshort 一个 16 位元 network 排列方式的数目
传回值: 一个 16 位元 host 排列方式的数目
说明: 因为 network 的排列方式与 host 的排列方式可能不同,所以我们需要此一函式来做转换。
(16) recv():自 Socket 接收资料。
格式: int PASCAL FAR recv( SOCKET s,char FAR *buf,int len,int flags );
参数: s Socket 的识别码,buf 存放接收到的资料的暂存区,len buf 的长度,flags 此函式被呼叫的方式
传回值: 成功 - 接收到的资料长度 (若对方 Socket 已关闭,则为 0)
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 此函式用来自连接式的 Datagram Socket 或 Stream Socket接收资料。对 Stream Socket 言,我们可以接收到目前有效的 (available)资料,但其数量不超过 len 的大小。若是此 Socket 设定 SO_OOBINLINE,且有 out-of-band 的资料未被读取,那麽只有 out-of-band 的资料被取出。
对 Datagram Socket 言,只取出第一个 datagram;若是该 datagram 大於使用者提供的储存空间,那麽只有该空间大小的资料被取出,多馀的资料将遗失,且回覆错误的讯息。 flags 的值可为 MSG_PEEK、MSG_OOB(*暂不提供此功能)的组合.
(17) recvfrom():读取一个 Datagram,并储存资料来源的位址。
格 式: int PASCAL FAR recvfrom( SOCKET s,char FAR *buf,int len,int flags,struct socketaddr FAR *from,int FAR *fromlen );
参 数: s Socket 的识别码,buf 存放接收到的资料的暂存区,len buf 的长度,flags 此函式被呼叫的方式,from 资料来源的位址,fromlen from 的大小
传回值: 成功 - 接收到的资料长度 (若对方 Socket 已关闭,则为 0)
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 此函式用来读取资料并记录资料来源的位址。对 Stream Socket 言,其作用与 recv() 相同,参数 from 及 fromlen 将不被用到。
(18) select():检查一或多个 Sockets 是否处於可读、可写或错误的状态。
格式: int PASCAL FAR select( int nfds,fd_set FAR *readfds,fd_set FAR *writefds,fd_set FAR *exceptfds,const struct timeval FAR *timeout );
参数: nfds 此参数在此并无作用,readfds 要被检查是否可读的 Sockets,writefds 要被检查是否可写的 Sockets,exceptfds 要被检查是否有错误的 Sockets,timeout 此函式该等待的时间。若为 NULL 时,表示 blocking,此函式会等到有事件发生。
传回值: 成功 - 符合条件的 Sockets 总数 (若 Timeout 发生,则为 0)
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 使用者可利用此函式来检查 Sockets 是否有资料可被读取,或是有空间可以写入,或是有错误发生。
(19) send():使用连接式的 Socket 传送资料。
格式: int PASCAL FAR send( SOCKET s,const char FAR *buf,int len,int flags );
参数: s Socket 的识别码,buf 存放要传送的资料的暂存区,len buf 的长度,flags 此函式被呼叫的方式
传回值: 成功 - 送出的资料长度
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 此函式适用於连接式的 Datagram 或 Stream Socket 来传送资料。对 Datagram Socket 言,若是 datagram 的大小超过限制,则将不会送出任何资料,并会传回错误值。若是传送 (transport) 系统内之储存空间不够存放这些要传送的资料,send() 将会被 block 住,除非该 Socket 被设定为 non-blocking 模式。使用者亦须注意 send()函式执行完成,并不表示资料已经成功地送抵对方了。 flags 的值可设为 MSG_DONTROUTE(*暂不提供此功能)及 MSG_OOB 的组合.
(20) sendto():将资料送到指定的目的地。
格式: int PASCAL FAR sendto( SOCKET s,const char FAR *buf,int len,int flags,const struct sockaddr FAR *to,int tolen );
参数: s Socket 的识别码,buf 存放要传送的资料的暂存区,len buf 的长度,flags 此函式被呼叫的方式,to 资料要送达的位址,tolen to 的大小
传回值: 成功 - 送出的资料长度
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 此函式适用於 Datagram 或 Stream Socket 来传送资料到指定的位址。对 Datagram Socket 言,若是 datagram 的大小超过限制,则将不会送出任何资料,并会传回错误值。对 Stream Socket 言,其作用与 send() 相同;参数 to 及 tolen 在此并无作用。 若是传送 (transport) 系统内之储存空间不够存放这些要传送的资料,sendto() 将会被 block 住,除非该Socket 被设定为 non-blocking 模式。使用者亦须注意 sendto() 函式执行完成,并不表示资料已经成功地送抵对方了。 flags 的值可设为 MSG_DONTROUTE(*暂不提供此功能)及 MSG_OOB 的组合.
本系统(WinKing)提供之 Windows Sockets API 介面乃是依照 1993年1月20日公布之 WINSOCK 第1.1版(如附录)中所定义之函式 (routine); 包括了30个Berkeley Software Distribution (BSD) 的函式以及16个符合 Windows Message-driven 特性的函式。
(21) setsockopt():设定 Socket 的状态。
格式: int PASCAL FAR setsockopt( SOCKET s,int level,int optname,const char FAR *optval,int optlen );
参数: s Socket 的识别码,level 选项设定的 level,optname 选项名称,optval 选项的设定值,optlen 选项设定值的长度
传回值: 成功 - 0
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 此函式用来设定 Socket 的一些选项,藉以更改其动作。
可更改的选项有: (参见WINSOCK第1.1版54页)
Value Type
-----------------------------------------------
SO_BROADCAST BOOL
*SO_DEBUG BOOL
SO_DONTLINGER BOOL
*SO_DONTROUTE BOOL
*SO_KEEPALIVE BOOL
SO_LINGER struct linger FAR*
SO_OOBINLINE BOOL
*SO_RCVBUF int
SO_REUSEADDR BOOL
*SO_SNDBUF int
TCP_NODELAY BOOL
(22) shutdown():停止 Socket 接收/传送的功能。
格式: int PASCAL FAR shutdown( SOCKET s, int how );
参数: s Socket 的识别码,how 代表该停止那些动作的标帜
传回值: 成功 - 0
失败 - SOCKET_ERROR (呼叫 WSAGetLastError()可得知原因)
说明: 此函式用来停止 Socket 的後续接收或传送的功能。
若 how 的值为 0,则不再接收资料。
若 how 的值为 1,则不再允许传送资料。
若 how 的值为 2,则不再接收且不再传送资料。
shutdown() 函式并没有将 Socket 关闭,所以该 Socket 所占用之资源必须在呼叫closesocket() 之後才会释放。
(23) socket():建立Socket。
格式: SOCKET PASCAL FAR socket( int af,int type,int protocol );
参数: af 目前只提供 PF_INET(AF_INET),type Socket 的型态 (SOCK_STREAM、SOCK_DGRAM),protocol 通讯协定(如果使用者不指定则设为0)
传回值: 成功 - Socket 的识别码
失败 - INVALID_SOCKET(呼叫 WSAGetLastError() 可得知原因)
说明: 此函式用来建立一 Socket,并为此 Socket 建立其所使用的资源。
Socket 的型态可为 Stream Socket 或 Datagram Socket。
(24) gethostbyaddr():利用某一 host 的位址来获取该 host 的资料。
格式: struct hostent FAR * PASCAL FAR gethostbyaddr( const char FAR *addr, int len, int type );
参数: addr network 排列方式的位址,len addr 的长度,type PF_INET(AF_INET)
传回值: 成功 - 指向 struct hostent 的指标
struct hostent
{
char FAR * h_name;
char FAR * FAR * h_aliases;
short h_addrtype;
short h_length;
char FAR * FAR * h_addr_list;
}
失败 - NULL (呼叫 WSAGetLastError() 可得知原因)
说明: 此函式是利用位址来获取 host的其他资料,如 host 的名称、别名,位址的型态、长度等。
(25) gethostbyname():利用某一 host 的名称来获取该 host 的资料。
格式: struct hostent FAR * PASCAL FAR gethostbyname( const char FAR *name );
参数: name host 的名称
传回值: 成功 - 指向 struct hostent 的指标
struct hostent
{
char FAR * h_name;
char FAR * FAR * h_aliases;
short h_addrtype;
short h_length;
char FAR * FAR * h_addr_list;
}
失败 - NULL (呼叫 WSAGetLastError() 可得知原因)
说明: 此函式是利用 host 名称来获取其他的资料,如 host 的位址、别名,位址的型态、长度等。
(26) gethostname():获取目前使用者使用的 host 的名称。
格式: int PASCAL FAR gethostname( char FAR *name, int namelen );
参数: name 用来存放 host 名称的暂存区,namelen name 的大小
传回值: 成功 - 0
失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 此函式用来获取 host 的名称。
(27) getprotobyname():依照通讯协定 (protocol) 的名称来获取该通讯协定的其他资料。
格式: struct protoent FAR * PASCAL FAR getprotobyname( const char FAR *name );
参数: name 通讯协定名称
传回值: 成功 - 一指向 struct protoent 的指标
struct protoent
{
char FAR * p_name;
char FAR * FAR * p_aliases;
short p_proto;
}
失败 - NULL (呼叫 WSAGetLastError() 可得知原因)
说明: 利用通讯协定的名称来得知该通讯协定的别名、编号等资料。
(28) getprotobynumber():依照通讯协定的编号来获取该通讯协定的其他资料。
格式: struct protoent FAR * PASCAL FAR getprotobynumber( int number );
参数: number 以 host 排列方式的通讯协定编号
传回值: 成功 - 一指向 struct protoent 的指标
struct protoent
{
char FAR * p_name;
char FAR * FAR * p_aliases;
short p_proto;
}
失败 - NULL (呼叫 WSAGetLastError() 可得知原因)
说明: 利用通讯协定的编号来得知该通讯协定的名称、别名等资料。
(29) getservbyname():依照服务 (service) 名称及通讯协定来获取该服务的其他资料。
格式: struct servent * PASCAL FAR getservbyname( const char FAR *name, const char FAR *proto );
参数: name 服务名称,proto 通讯协定名称
传回值: 成功 - 一指向 struct servent 的指标
struct servent
{
char FAR * s_name;
char FAR * FAR * s_aliases;
short s_port;
char FAR * s_proto;
}
失败 - NULL (呼叫 WSAGetLastError() 可得知原因)
说明: 利用服务名称及通讯协定来获得该服务的别名、使用的port编号等。
(30) getservbyport():依照服务 (service) 的 port 编号及通讯协定来获取该服务的其他资料。
格式: struct servent * PASCAL FAR getservbyport( int port, const char FAR *proto );
参数: port 服务的 port 编号,proto 通讯协定名称,传回值: 成功 - 一指向 struct servent 的指标
struct servent
{
char FAR * s_name;
char FAR * FAR * s_aliases;
short s_port;
char FAR * s_proto;
}
失败 - NULL (呼叫 WSAGetLastError() 可得知原因)
说明: 利用 port 编号及通讯协定来获得该服务的名称、别名等。