请看我的代码!用非阻塞的accept函数要注意什么?

发布于 2022-07-19 21:35:24 字数 2249 浏览 10 评论 9

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

傻比既视感 2022-07-25 11:02:03

原帖由 mq110 于 2006-7-25 20:50 发表

这样肯定是出错了.

那是不是说accpet返回-1,然后再判断error是不是EWOULDBLOCK,如果是那么不推出,就可以继续循环?

你怎么这么可爱啊 2022-07-25 10:55:09

原帖由 meijianchi 于 2006-7-25 20:44 发表

accept为-1的时候,是不是返回EWOULDBLOCK,还有什么我不知道了
这样不表明出错了吧?

这样肯定是出错了.

水晶透心 2022-07-25 10:32:47

原帖由 mq110 于 2006-7-25 20:45 发表
线程池..比较节省资源,开始的时候开线程池的话,以后就不需要为创建花费资源了,节省时间.

我是初学者,还不会用这个东西,现在要写一个这样的程序,能跑起来

想用非阻塞的accept来做,不知道要怎么处理

满身野味 2022-07-25 09:19:42

线程池..比较节省资源,开始的时候开线程池的话,以后就不需要为创建花费资源了,节省时间.

妄断弥空 2022-07-25 09:11:40

原帖由 mq110 于 2006-7-25 20:18 发表
返回-1出错,返回非负 就是文件描述符.就可以send ,recv等操作了.

accept为-1的时候,是不是返回EWOULDBLOCK,还有什么我不知道了
这样不表明出错了吧?

小梨窩很甜 2022-07-24 22:53:58

原帖由 mq110 于 2006-7-25 20:20 发表
不过为什么不把accept 放在while循环开始处呢?
我一般是这样做. accept放在while循环的开始处,有新来的连接 派生进程处理,如果需要响应多个描述符的时候就用非阻塞的方式.

我可不能用进程处理,因为我要做的是,连接很多客户端,然后客户端发数据包,根据包中的转发类型来决定是发个另一个客户端,还是所有客户端

你说的办法可行吗?您有什么好办法吗?

漫漫岁月 2022-07-24 03:47:28

>>
>>
>>刚看来得
>>
>>
阻塞和非阻塞
  阻塞函数在完成其指定的任务以前不允许程序调用另一个函数。例如,程序执行一个读数据的函数调用时,在此函数完成读操作以前将不会执行下一程序语句。当服务器运行到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 */
};

与往事干杯 2022-07-23 23:43:12

不过为什么不把accept 放在while循环开始处呢?
我一般是这样做. accept放在while循环的开始处,有新来的连接 派生进程处理,如果需要响应多个描述符的时候就用非阻塞的方式.

[ 本帖最后由 mq110 于 2006-7-25 20:31 编辑 ]

晒暮凉 2022-07-22 17:09:30

返回-1出错,返回非负 就是文件描述符.就可以send ,recv等操作了.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文