请看我的代码!用非阻塞的accept函数要注意什么?
while(1)
{
//每次循环,读写集初始化
rset = allset;
wset = allset;
//设置非阻塞I/O
io_block_var = fcntl(tcp_fd, F_GETFL, 0);
fcntl(tcp_fd, F_SETFL, io_block_var|O_NONBLOCK);
nready = select(maxfd + 1, &rset, NULL, NULL, NULL);
//检查读集合,如果对应的TCP socket有新连接,则处理
if (FD_ISSET(tcp_fd, &rset))
{
sin_size = sizeof(struct sockaddr_in);
//接收新连接
if ((accept_fd = accept(tcp_fd, (struct sockaddr*)&remote_addr, &sin_size)) == -1)
{
printf("TCP SOCKET accept ERROR!n");
continue;
}
.................
这样写accept的返回值都有哪些?应该怎么做?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
那是不是说accpet返回-1,然后再判断error是不是EWOULDBLOCK,如果是那么不推出,就可以继续循环?
这样肯定是出错了.
我是初学者,还不会用这个东西,现在要写一个这样的程序,能跑起来
想用非阻塞的accept来做,不知道要怎么处理
线程池..比较节省资源,开始的时候开线程池的话,以后就不需要为创建花费资源了,节省时间.
accept为-1的时候,是不是返回EWOULDBLOCK,还有什么我不知道了
这样不表明出错了吧?
我可不能用进程处理,因为我要做的是,连接很多客户端,然后客户端发数据包,根据包中的转发类型来决定是发个另一个客户端,还是所有客户端
你说的办法可行吗?您有什么好办法吗?
>>
>>
>>刚看来得
>>
>>
阻塞和非阻塞
阻塞函数在完成其指定的任务以前不允许程序调用另一个函数。例如,程序执行一个读数据的函数调用时,在此函数完成读操作以前将不会执行下一程序语句。当服务器运行到accept语句时,而没有客户连接服务请求到来,服务器就会停止在accept语句上等待连接服务请求的到来。这种情况称为阻塞(blocking)。而非阻塞操作则可以立即完成。比如,如果你希望服务器仅仅注意检查是否有客户在等待连接,有就接受连接,否则就继续做其他事情,则可以通过将Socket设置为非阻塞方式来实现。非阻塞socket在没有客户在等待时就使accept调用立即返回。
#include
#include
……
sockfd = socket(AF_INET,SOCK_STREAM,0);
fcntl(sockfd,F_SETFL,O_NONBLOCK);
……
通过设置socket为非阻塞方式,可以实现"轮询"若干Socket。当企图从一个没有数据等待处理的非阻塞Socket读入数据时,函数将立即返回,返回值为-1,并置errno值为EWOULDBLOCK。但是这种"轮询"会使CPU处于忙等待方式,从而降低性能,浪费系统资源。而调用select()会有效地解决这个问题,它允许你把进程本身挂起来,而同时使系统内核监听所要求的一组文件描述符的任何活动,只要确认在任何被监控的文件描述符上出现活动,select()调用将返回指示该文件描述符已准备好的信息,从而实现了为进程选出随机的变化,而不必由进程本身对输入进行测试而浪费CPU开销。Select函数原型为:
int select(int numfds,fd_set *readfds,fd_set *writefds,
fd_set *exceptfds,struct timeval *timeout);
其中readfds、writefds、exceptfds分别是被select()监视的读、写和异常处理的文件描述符集合。如果你希望确定是否可以从标准输入和某个socket描述符读取数据,你只需要将标准输入的文件描述符0和相应的sockdtfd加入到readfds集合中;numfds的值是需要检查的号码最高的文件描述符加1,这个例子中numfds的值应为sockfd+1;当select返回时,readfds将被修改,指示某个文件描述符已经准备被读取,你可以通过FD_ISSSET()来测试。为了实现fd_set中对应的文件描述符的设置、复位和测试,它提供了一组宏:
FD_ZERO(fd_set *set)----清除一个文件描述符集;
FD_SET(int fd,fd_set *set)----将一个文件描述符加入文件描述符集中;
FD_CLR(int fd,fd_set *set)----将一个文件描述符从文件描述符集中清除;
FD_ISSET(int fd,fd_set *set)----试判断是否文件描述符被置位。
Timeout参数是一个指向struct timeval类型的指针,它可以使select()在等待timeout长时间后没有文件描述符准备好即返回。struct timeval数据结构为:
struct timeval {
int tv_sec; /* seconds */
int tv_usec; /* microseconds */
};
不过为什么不把accept 放在while循环开始处呢?
我一般是这样做. accept放在while循环的开始处,有新来的连接 派生进程处理,如果需要响应多个描述符的时候就用非阻塞的方式.
[ 本帖最后由 mq110 于 2006-7-25 20:31 编辑 ]
返回-1出错,返回非负 就是文件描述符.就可以send ,recv等操作了.