免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3099 | 回复: 12
打印 上一主题 下一主题

帮我解决一下这个Socket问题!急! [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2003-03-03 20:31 |只看该作者 |倒序浏览
这是一个比较典型的select的例子代码,
现在我的问题就是怎么知道在rset里哪些
socket可以读写呢。


FD_ISSET(sockfd, &rset))
这个语句只能说明sockfd在rset里,并不能说明
sockfd可以读写啊??




  1. for ( ; ; ) {
  2. rset = allset; /* structure assignment */
  3. nready = Select(maxfd+1, &rset, NULL, NULL, NULL);
  4. if (FD_ISSET(listenfd, &rset)) { /* new client connection */
  5. clilen = sizeof(cliaddr);
  6. connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);
  7. for (i = 0; i < FD_SETSIZE; i++)
  8. if (client[i] < 0) {
  9. client[i] = connfd; /* save descriptor */
  10. break
  11. }
  12. if (i == FD_SETSIZE) err_quit("too many clients");
  13. FD_SET(connfd, &allset); /* add new descriptor to set */
  14. if (connfd >; maxfd) maxfd = connfd; /* for select */
  15. if (i >; maxi) maxi = i; /* max index in client[] array */
  16. if (--nready <= 0) continue; /* no more readable descriptors */
  17. }
  18. for (i = 0; i <= maxi; i++) { /* check all clients for data */
  19. if ( (sockfd = client[i]) < 0) continue;
  20. if (FD_ISSET(sockfd, &rset)) {
  21. if ( (n = Readline(sockfd, line, MAXLINE)) == 0) {
  22. /*4connection closed by client */
  23. Close(sockfd);
  24. FD_CLR(sockfd, &allset);
  25. client[i] = -1;
  26. }
  27. else Writen(sockfd, line, n);
  28. if (--nready <= 0) break; /* no more readable descriptors */
  29. }
  30. }
  31. } //end of for loop
复制代码

论坛徽章:
0
2 [报告]
发表于 2003-03-03 20:59 |只看该作者

帮我解决一下这个Socket问题!急!

哦,这个代码写的还不错。我好象就这个问题回复过一篇了。
select()返回后,rset一般而言是被修改了,只有那些发生了可读事件的套接字在rset中有对应的设置。对listenfd而言可能是有了连接到达。对client_fd而言就是有了数据或连接关闭,因为rset的意思就是要关注可读事件的发生的。所以一定是有了某些数据或事件。如果你想关注可写事件或其他时间,你可以设置select()的第3、4个参数,就象设置rset一样。

论坛徽章:
0
3 [报告]
发表于 2003-03-03 22:03 |只看该作者

帮我解决一下这个Socket问题!急!

但是关键问题是那个刚刚加入的new_fd根本不可以读写啊,
因为客户只进行了connect的操作,而没有send数据或者关闭,
怎么FD_ISSET(new_fd,&amp;rset)就>;0了呢??

请各位大侠告知!

论坛徽章:
0
4 [报告]
发表于 2003-03-03 22:19 |只看该作者

帮我解决一下这个Socket问题!急!

请问各位:
在第一次if (FD_ISSET(sockfd, &amp;rset)) 是,
if是真还是假,

注:服务器socket描述符没有放到client数组里面



--------------------------
革命尚未成功,同志还需努力!

论坛徽章:
0
5 [报告]
发表于 2003-03-04 11:58 |只看该作者

帮我解决一下这个Socket问题!急!

/*
主要的思想是用一个fd_set---->;allset表示所有想监控的socket。为什么要用这个呢,因为每次调用
select()后,rset中将只包含发生了网络事件(连接到达,数据到达,连接关闭等)的socket的信息。这样
如果下次再用这个rset调用select()则结果将只是对上次发生了网络事件的那些socket进行监控,而不是
对所有的socket进行监控,这可不是程序想要的效果。你不防把fd_set想象成一个位图,如果想监控某个
socket, 则将fd_set中的相应的代表该socket的标志设置成1(用FD_SET)。这样就可以告诉select()系统
调用你想知道哪些socket的什么事情了。而select返回的时候,如果没有出错的话,则其返回值表示发生
事件的socket有几个,而select()也会相应的修改你传递给它的参数的内容,这时候将只有发生了网络事件
的socket在fd_set中对应的标志被设置为1,以便你使用FD_ISSET()进行查询。所以,这里为了方便,
使用一个全局的allset用来保存所有socket的标志,但不会用它去调用select(),每次在调用select()之前,
都将allset的值拷贝到rset,这样就不必每次调用之后重新对rset设置一遍了,省了许多麻烦。再次强调
一遍,select()调用前后rset的内容一般是不一样的,整个循环总是要监控所有的socket,每次调用
select()之前都需要对你想监控的fd_set重新设置。
        nready = Select(maxfd+1, &amp;rset, NULL, NULL, NULL);
表示你只想监控rset中的那些socket的可读事件,返回值nready或者是错误值,或者是发生了事件的socket
的数量。程序的意思是有一个listenfd用来监听新的连接,用一个client_fd数组保存所有被accept()返回的
表示新的连接的socket的描述符。在进入循环之前,应该将client_fd[]全设置为-1,而将listen_fd用
FD_SET设置到allset中。这样,第一次进入循环的时候,我们只对listen_fd进行select(),当它正确返回后,
表示有新的连接到达,于是第四行到第21行就是接受这个新的连接并返回一个新的socket,然后将这个新的
socket保存在数组client_fd[]中,并相应地更新max_fd, maxi,设置allset。现在allset中应该有了两个
socket,一个是原来的listen_fd,一个是我们刚接受的新的fd(将在下一次select中监控是否有数据到达)。
第19行的--nready将使nready为0,进入下一次循环。
现在是第2次select()。rset=allset;将使rset中包含listen_fd和那个我们刚刚创建的新的socket,这次select()
调用的返回,可能是有了新的连接(listen_fd有效),或者是数据到达conn_fd,或者两个都有。这一次,我们就
可以根据FD_ISSET的判断得出相应的结论而采取对应的动作。当然,如果新连接到达,我们和上次一样接受一个
新的连接并保存到client_fd[]中;但也可能是发生了可读事件,于是所有数组client_fd[],并用FD_ISSET判断是哪个
socket发生了可读事件。(对我们的第2次调用来看,只有一个可能,就是上次我们接受的那个连接。)
以后的情况就类似了。

从上面的论述回答你的问题:
第三贴: 刚进入循环的时候,只监控listen_fd的状况,new_fd是在以后逐渐添加的(都放到client_fd[]数组里)
第四贴: 更正一下,你想问的是listen_fd,而非sockfd. 在进入循环前,已经将该FD加入allset,所以第一次
select()返回(正确返回)肯定是listen_fd发生了连接请求。

明白了吗?本来想写一个完整的,而非代码片段,但现在没时间,如果有空我希望可以.
*/

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
6 [报告]
发表于 2003-03-04 12:15 |只看该作者

帮我解决一下这个Socket问题!急!

原帖由 "pcerma" 发表:
请问各位:
在第一次if (FD_ISSET(sockfd, &amp;rset)) 是,
if是真还是假,

注:服务器socket描述符没有放到client数组里面


当然是真了,你刚set过了么。

其实雷斯林在你的上一篇提问中就回答了,你仔细看看。

这段代码一样有问题。FD_SET应该在loop的最后执行。而且是FD_SET所有的
sockfd

原帖由 "pcerma" 发表:

但是关键问题是那个刚刚加入的new_fd根本不可以读写啊,
因为客户只进行了connect的操作,而没有send数据或者关闭,
怎么FD_ISSET(new_fd,&amp;rset)就>;0了呢??


给你个链接,讲的非常详细,自己看看吧
http://fanqiang.com/a4/b7/20011115/0808001567.html

论坛徽章:
0
7 [报告]
发表于 2003-03-04 12:45 |只看该作者

帮我解决一下这个Socket问题!急!

select 函数用法

使用前应该把关心的文件描述符使用fd_set设置


select返回时会改变输入的fd_set值
此时fd_set内只保存满足条件的描述符(如已变成可读)

论坛徽章:
0
8 [报告]
发表于 2003-03-04 13:12 |只看该作者

帮我解决一下这个Socket问题!急!

我的问题已经解决了,谢谢个位的帮助。


无双:在select之后,fd_set中不会只保存改变了的信息描述符,
      原先的加入到fd _set中的描述符都存在,select只不过改变
      了描述符的状态。

论坛徽章:
0
9 [报告]
发表于 2003-03-04 13:22 |只看该作者

帮我解决一下这个Socket问题!急!

gadfly:
        那个网页我看过的,第一次写的时候就是用它的思想,不过它没有说清楚一个问题,就是应该分两个fd_set的变量:rset(没有将accept得到的连接描述符加入),allset(加入了accept得到的连接描述符)。
      1)在select后,对fd_set用FD_ISSET进行判断,看哪些连接描述符可读,需要使用rset;如果使用allset,那么新加入的(通过accept)描述符是可读的,那么执行recv,结果阻塞在此,因为客户没有发送消息。

以上代码片断是正确的,我经调试。


再次感谢!

论坛徽章:
0
10 [报告]
发表于 2003-03-04 13:27 |只看该作者

帮我解决一下这个Socket问题!急!

无双:
    转念一想,可能还是我错了,
     select之后可能只保存了改变了状态的socket
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP