Chinaunix

标题: accept的问题,求助! [打印本页]

作者: andyY    时间: 2007-03-28 17:14
标题: accept的问题,求助!
环境:  一个linux c 的服务器,一个win vc 的客户端,另一个win vb 的客户端;
问题:
1、accept 返回 0
    vc 的客户端使用都很正常;而vb的客户端使用时,服务器accept会返回0
    很奇怪怎么会得到 STDIN 的默认描述符呢(没有关闭的)?

2、文件描述符0上,接收正常,发送有时失败
     使用vb 的客户端,accept 得到 0, 服务端能接收客户端消息,但是发送失败: Bad file descriptor
     之后再使用 vc 的客户端, 同样还是0,但此时服务端接收、发送都时成功
    (其间服务端没有重启)


到底怎么回事呢?太奇怪了

代码在第10贴

[ 本帖最后由 andyY 于 2007-3-28 19:43 编辑 ]
作者: net_robber    时间: 2007-03-28 17:20
accept,第三个参数,注意一下
作者: isnowran    时间: 2007-03-28 17:24
你是不是把标准输入关闭了?
作者: andyY    时间: 2007-03-28 17:49
在前面有定义的


  1.   ...
  2.   struct sockaddr_in *peer;
  3.   struct sockaddr_in peer_;
  4.   socklen_t *len;
  5.   socklen_t len_;

  6.   if( NULL==addr )  //输入的参数,指针类型
  7.   {
  8.     peer = NULL;
  9.     len = NULL;
  10.   }
  11.   else
  12.   {
  13.     peer = &peer_;
  14.     len = &len_;
  15.   }

  16.   ...
  17.   while(true)
  18.   {
  19.      ....
  20.   }
复制代码


程序里标准输入从来没有关闭过。。。

[ 本帖最后由 andyY 于 2007-3-28 17:51 编辑 ]
作者: mq110    时间: 2007-03-28 17:51
原帖由 net_robber 于 2007-3-28 17:20 发表
accept,第三个参数,注意一下



楼主看这个回复就够了。

重新去man

&len;
作者: flw    时间: 2007-03-28 17:51
原帖由 andyY 于 2007-3-28 17:49 发表
在前面有定义的
  [CODE]

  ...
  struct sockaddr_in *peer;
  struct sockaddr_in peer_;
  socklen_t *len;
  socklen_t len_;

  if( NULL==addr )  //输入的参数,指针类型
  {
    peer = NUL ...

我倒很有兴趣了解一下你这俩指针都指向什么地方了?
这种写法我还是第一次见……
作者: flw    时间: 2007-03-28 17:52
  1.   struct sockaddr_in *peer;
  2.   struct sockaddr_in peer_;
  3.   socklen_t *len;
  4.   socklen_t len_;

  5.     peer = &peer_;
  6.     len = &len_;
复制代码

你太有才了!
作者: mq110    时间: 2007-03-28 17:54

  1.   if( NULL==addr )  //输入的参数,指针类型
  2.   {
  3.     peer = NULL;
  4.     len = NULL;
  5.   }
  6.   else
  7.   {
  8.     peer = &peer_;
  9.     len = &len_;
  10.   }
复制代码


这是你DIY的吧?
作者: andyY    时间: 2007-03-28 17:56
以前写的,改掉了,第一贴也更新了

故障还是一样的,能帮我分析下吗?

[ 本帖最后由 andyY 于 2007-3-28 18:28 编辑 ]
作者: net_robber    时间: 2007-03-28 19:05
楼主上面的代码,没有看到调用socket函数


建议你从socket那一行都贴出来


如果你有那么一行
作者: andyY    时间: 2007-03-28 19:38
.h

  1. #ifndef __SOCK_ACCEPTOR_H
  2. #define __SOCK_ACCEPTOR_H

  3. #include "Sock_Stream.h"
  4. #include "Net_Addr.h"
  5. #include "Sock.h"

  6. class CNF_Sock_Acceptor : public CNF_Sock
  7. {
  8. public:
  9.   enum
  10.   {
  11.     DEFAULT_BACKLOG = 3
  12.   };

  13.   bool valid();

  14.   CNF_HANDLE get_handle();

  15.   int open( const CNF_Net_Addr& addr,
  16.             bool reuse = true,
  17.             int backlog = DEFAULT_BACKLOG);

  18.   int close(void);
  19.   
  20.   // timeout_sec: >0   select
  21.   //              <=0  directly
  22.   // return:  0 successful
  23.   //         -1 failed
  24.   int accept( CNF_Sock_Stream& stream,
  25.               CNF_Net_Addr* peer = NULL,
  26.               int timeout_sec = 0);
  27. };

  28. #endif
复制代码


.cpp

  1. #include "Sock_Acceptor.h"

  2. #include <sys/select.h>
  3. #include <sys/socket.h>
  4. #include <sys/types.h>
  5. #include <sys/time.h>
  6. #include <unistd.h>
  7. #include <string.h>
  8. #include <stdio.h>

  9. #include <iostream>
  10. #include <string.h>
  11. #include <errno.h>

  12. bool CNF_Sock_Acceptor::valid()
  13. {
  14.   return INVALID_HANDLE != handle();
  15. }

  16. CNF_HANDLE CNF_Sock_Acceptor::get_handle()
  17. {
  18.   return handle();
  19. }

  20. int CNF_Sock_Acceptor::open( const CNF_Net_Addr& addr, bool reuse, int backlog)
  21. {
  22.   //check
  23.   if( valid() )
  24.     close();

  25.   //socket
  26.   int ret = socket( PF_INET, SOCK_STREAM, 0);
  27.   if( 0>ret )
  28.     return -1;

  29.   handle( ret );

  30.   set_option( MASK_REUSE_ADDR, reuse ? 1 : 0);

  31.   //bind
  32.   struct sockaddr_in sa = addr;
  33.   ret = bind( handle(), (struct sockaddr*)&sa, sizeof(sa) );
  34.   if( 0>ret )
  35.     return -1;

  36.   //listen
  37.   return listen( handle(), backlog);
  38. }

  39. int CNF_Sock_Acceptor::close(void)
  40. {
  41.   int h = handle();
  42.   return ::close( h );
  43. }

  44. int CNF_Sock_Acceptor::accept( CNF_Sock_Stream& stream,
  45.                                CNF_Net_Addr* addr,
  46.                                int timeout_sec)
  47. {
  48.   //check
  49.   if( !valid() )
  50.     return -1;

  51.   // address
  52.   struct sockaddr_in peer;
  53.   socklen_t len = sizeof(peer);

  54.   //handle
  55.   CNF_HANDLE h = handle();

  56.   //timeout
  57.   struct timeval tv;
  58.   tv.tv_sec = timeout_sec>0 ? timeout_sec : 0;
  59.   tv.tv_usec = 0;
  60.    
  61.   //select
  62.   fd_set rd;
  63.   FD_ZERO( &rd );
  64.   FD_SET( h, &rd);

  65.   while(true)
  66.   {
  67.     // 检查有效事件
  68.     FD_SET( h, &rd);
  69.     int ret = select( h+1, &rd, NULL, NULL, &tv);
  70.     if( 0>ret )
  71.     {
  72.       if( EINTR == errno )
  73.         continue; // select: 打断,继续
  74.       else
  75.       {
  76.         perror( "select failed" );
  77.         return -1;// select: 失败
  78.       }

  79.     }else if( 0 == ret)
  80.     {
  81.       std::cout<<"accept @ "<<h<<": timeout"<<std::endl;
  82.       return -1;  // select: 超时
  83.     }

  84.     // 检查有效连接
  85.     int new_handle = ::accept( h, (struct sockaddr*)&peer, &len);
  86.     std::cerr<<"accept @ "<<h<<" return "<<new_handle<<std::endl;
  87.     if( 0 > new_handle)
  88.     {
  89.       perror("accept failed");
  90.       return -1;  // accept:失败
  91.     }

  92.     if ( 0 == stream.set_handle( new_handle ) )
  93.     {
  94.       if( addr )
  95.       {
  96.         *addr = peer;
  97.       }

  98.       return 0;   // 设置:成功
  99.     }

  100.     std::cerr<<"stream.set_handle() failed"<<std::endl;
  101.     break;        // 设置: 失败
  102.   }

  103.   return -1;
  104. }
复制代码

作者: andyY    时间: 2007-03-28 19:58
运行后程序的输出

.........

//VB 客户端第一次

process() @ 9 @ handle_input()
accept @ 9 return 10

recv @ 10 get 50 bytes

send: part1 = 33, part2 = 28

process() @ 10 @ handle_input()
recv @ 10: peer closed
process() @ 10 @ handle_close()

// VB 客户端第二次

process() @ 9 @ handle_input()
accept @ 9 return 0


send: part1 = -1, part2 = -1
send @ 0 failed: Bad file descriptor


// VC 客户端

process() @ 9 @ handle_input()
accept @ 9 return 0

process() @ 0 @ handle_input()
recv @ 0 get 101 bytes

send: part1 = 33, part2 = 0

process() @ 0 @ handle_input()
recv @ 0 get 33 bytes

process() @ 0 @ handle_input()
recv @ 0 get 33 bytes

send: part1 = 33, part2 = 896

......
作者: andyY    时间: 2007-03-29 11:45
有人能帮我看看吗?
作者: isnowran    时间: 2007-03-29 12:47
handle 是怎么定义的?
作者: andyY    时间: 2007-03-29 13:08
typedef int CNF_HANDLE;

CNF_HANDLE CNF_Sock::handle();
作者: isnowran    时间: 2007-03-29 13:31
原帖由 andyY 于 2007-3-29 13:08 发表
typedef int CNF_HANDLE;

CNF_HANDLE CNF_Sock::handle();

据我所知,这玩意叫声明,非定义
作者: soul_of_moon    时间: 2007-03-29 13:55
我怎么越看那个select和accept,越感到别扭。
作者: deadlylight    时间: 2007-04-02 10:34
每轮循环都应该执行FD_ZERO( &rd );
作者: soul_of_moon    时间: 2007-04-02 10:40
原帖由 deadlylight 于 2007-4-2 10:34 发表
每轮循环都应该执行FD_ZERO( &rd );

no
作者: deadlylight    时间: 2007-04-02 11:21
select返回之后应该用FD_ISSET看看是不是你想要的那个fd




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2