ZLIP实现了BSD socket的socket, sendto, recvfro, connect, bind, listen,
accept, send, recv, closesocket, shutdown, getpeername, getsockname,
htonl, htons, ntohl, ntohs, inet_addr,inet_ntoa,ioctlsocket,setsockopt,
getsockopt,select共23个接口函数。
select函数用于获取一个或多个socket的状态,如果没有任何一个指定的socket处于指定的状态,则函数处于阻塞状态,直到有一个socket处于指定的状态后返回。
int select(
int nfds,
fd_set FAR *readfds,
fd_set FAR *writefds,
fd_set FAR *exceptfds,
const struct timeval FAR *timeout
);
参数
nfds
[in] 该参数是为兼容linux
socket而设计,这里不使用。
readfds
[in/out] readfds
指向fd_set类型的结构,每个fd_set结构体内含有多个套接字。Readfds中包含的套接字是要进行可
读性检测的套接字。函数返回的时候Readfds中包含处于可读状态的套接字。NULL表示select不进行可读性检测。
writefds
[in/out] writefds中包含的套接字是要进行可写性检测的套接字。函数返回的时候writefds中包含处于可写状态的套
接字。NULL表示select不进行可写性检测。
exceptfds
[in/out] exceptfds中包含的套接字是要进行异常检测的套接字。函数返回的时候exceptfds中包含处于异常状态的套
接字。 NULL表示select不进行异常检测。
timeout
[in] 最长等待时间,如果为NULL,则为永久等待,直到有一个socket符合指定的要求。timeout内容是不会在函数中修
改的。如果timeout中的值为0,则相当于非阻塞方式的检测。
返回值: 返回所有准备好的fd_set中的socket的个数总和,返回0表示等待超时。
描述
可读性:可读性是指如下情况:
(1) 如果该socket调用过listen(),可读时表示有连接等待接受,可使用accpet 从该socket接受连接。使用select()进行accept检测的参考例子如下:
zl_s32 s32tmp;
struct timeval t;
fd_set r;
struct sockaddr_in DT_XDATA dest_addr, dest_addr_get;
dest_addr_get.sin_addr = IPAddr;
dest_addr_get.sin_port = 1024;
/* readable when can accept */
s = socket(PF_INET, SOCK_STREAM, 0);
bind(s,&dest_addr_get, sizeof(struct sockaddr_in));
listen(s,5);
printf("\nwait for connection...");
FD_ZERO(&r);
FD_SET(s, &r);
t.tv_sec = 10;
t.tv_usec = 100;
if(select(0, &r, NULL, NULL, &t) != 0)
{
if(FD_ISSET(s, &r))
printf("\n is acceptable");
s32tmp = sizeof(struct sockaddr_in);
if((ss[0] = accept(s, &dest_addr, &s32tmp))
!= SOCK_ERR)
{
printf("\naccept
from %s, port %d", inet_ntoa(&dest_addr), dest_addr.sin_port);
}
else
{
FIND_ERROR;
}
}
else
{
printf("no
connection in %d s",t.tv_sec);
}
socketclose(s);
(2) 当检测到s可读时,即使在阻塞模式下,s也可以调用recv()或recvfrom()而不阻塞。
(3) 当连接被closed、reset的时候也是可读的。为了和(2)进行区别可以通过调用recv来检查(当可读时,用recv()或recvfrom()返回0表明是情况(3))。
可写性:
(1) 表示调用connect后,连接已经建立,可以发送数据了,所以select可以用于非阻塞状态的connect函数是否成功建立连接的检测。
(2) 表示发送缓存还有空余并且对方接收缓冲区不为0,可以发送数据。
异常:
当TCP发生connect()连接失败、对方发送RST、对方中断连接等错误是人为发生了异常。
当selcet返回的时候,readfds 、writefds 、exceptfds 中没有准备好的fd将被删除。关于fd_set有如下定义:
(1) FD_SETSIZE:这个宏定义表示fd_set中的socket的最大数量,例如64。
(2) FD_CLR(s, *set):从set中将s删除。在使用fd_set之前应该先清空。
(3) FD_ISSET(s, *set):s是否存在于set中。
(4) FD_SET(s, *set):将s加入set中。
(5) FD_ZERO(*set):将set清空。