• 网络编程一些常见问题总结


    1 设置网络socket非阻塞:

    u_long has = 1;
    ioctl(m_sock, FIONBIO , &has);

    这个函数很有可能返回success,却并没有设置成功。
    windows对此有优化,对于linux版本应采用fcntl设置。

    总结如下:

    int
    make_socket_nonblocking(sockfd fd)
    {
    #ifdef WIN32
        {
            u_long nonblocking = 1;
            if (ioctlsocket(fd, FIONBIO, &nonblocking) == SOCKET_ERROR) {
                cout << "fcntl failed, fd is : " << fd; 
                
                return -1;
            }
        }
    #else
        {
            int flags;
            if ((flags = fcntl(fd, F_GETFL, NULL)) < 0) {
                cout << "fcntl failed, fd is : " << fd;
                return -1;
            }
            if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
                cout << "fcntl failed, fd is : " << fd;
                return -1;
            }
        }
    #endif
        return 0;
    }

    2 windows环境下查看错误

    使用WSAGetLastError函数需要配置
    
    lib,"ws2_32.lib"
    

    3 EPOLLET这个宏是最小int

    EPOLLET这个宏的数值为-2147483648, 是能表示的最小int值。

    4

    make: 警告:检测到时钟错误。您的创建可能是不完整的。

    以通过ls -l查看具体的是哪个文件的时间错了,就可以对症下药了,直接 " touch 对应文件 " 就可以解决这个问题。

    或者读者可以用 " touch * " 来更新整个项目文件的时间,这也可以解决问题。

     

    5select fd_set 对于不同平台实现是不同的

    在windows平台实现
    typedef struct fd_set {
            u_int fd_count;               /* how many are SET? */
            SOCKET  fd_array[FD_SETSIZE];   /* an array of SOCKETs */
    } fd_set;
    很明了,一个计数的fd_count,另一个就是SOCKET数组。其中,FD_SETSIZE是可以设置的。
    整个fd_set的过程实际上就是将对应的fd_count作为数组下标,数组元素存储的是对应socket fd。

    比如说当前读事件集合readset的fd_count 为7,当要监控socket fd为5 的读事件到来时,

    那么readset这个集合中下标为8的数组元素为5,fd_count  = 8以此类推。

    当调用select时,会返回对应读,写集合所有的描述符数组,并且重置内部的fd_count数量,

    然后分别调用读写函数即可。

    下面是fd_set在linux下的实现:
    typedef struct
      {
        /* XPG4.2 requires this member name.  Otherwise avoid the name
           from the global namespace.  */
    #ifdef __USE_XOPEN
        __fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];
    # define __FDS_BITS(set) ((set)->fds_bits)
    #else 
        __fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS];
    # define __FDS_BITS(set) ((set)->__fds_bits)
    #endif
      } fd_set;

    根据UNIX网络编程对fd_set的介绍,fd_set是个整数数组,用每个bit位来表示fd的。比如,一个32位整数,则数组第一个整数表示0-31的fd,以此类推,第二个整数表示32-63
    查看linux的FD_SET、FD_CLR是用汇编实现的。根据说明可以知道,就是给bit置位。

    fd_set在不同平台实现的机制不一样,select第一个参数在linux环境下表示最大描述符数+1。windows无意义。

    下面是我根据libevent早期版本实现的一套select模型:

      1 #include "modelmanager.h"
      2 
      3 
      4 #ifdef WIN32
      5 #include "netmodeldef.h"
      6 #define XFREE(ptr) do { if (ptr) free(ptr); } while (0)
      7 
      8 
      9 struct win_fd_set {
     10     u_int fd_count;
     11     SOCKET fd_array[1];
     12 };
     13 
     14 struct win32op {
     15     unsigned num_fds_in_fd_sets;
     16     int resize_out_sets;
     17     struct win_fd_set *readset_in;
     18     struct win_fd_set *writeset_in;
     19     struct win_fd_set *readset_out;
     20     struct win_fd_set *writeset_out;
     21     struct win_fd_set *exset_out;
     22     unsigned signals_are_broken : 1;
     23 };
     24 
     25 static void *win32_init(void *);
     26 static int win32_add(void *, sockfd, short old, short events, void *_idx);
     27 static int win32_del(void *, sockfd, short old, short events, void *_idx);
     28 static int win32_dispatch(void *base, struct timeval *);
     29 static void win32_dealloc(void *);
     30 
     31 struct ModelOp win32ops = {
     32     "win32",
     33     win32_init,
     34     win32_add,
     35     win32_del,
     36     win32_dispatch,
     37     win32_dealloc,
     38 };
     39 
     40 #define FD_SET_ALLOC_SIZE(n) ((sizeof(struct win_fd_set) + ((n)-1)*sizeof(SOCKET)))
     41 
     42 static int
     43 grow_fd_sets(struct win32op *op, unsigned new_num_fds)
     44 {
     45     size_t size;
     46 
     47     if( !(new_num_fds >= op->readset_in->fd_count &&
     48         new_num_fds >= op->writeset_in->fd_count) )
     49         return -1;
     50     if( !(new_num_fds >= 1) )
     51         return -1;
     52 
     53     size = FD_SET_ALLOC_SIZE(new_num_fds);
     54     if (!(op->readset_in = (struct win_fd_set *)realloc(op->readset_in, size)))
     55         return (-1);
     56     if (!(op->writeset_in = (struct win_fd_set *)realloc(op->writeset_in, size)))
     57         return (-1);
     58     op->resize_out_sets = 1;
     59     op->num_fds_in_fd_sets = new_num_fds;
     60     return (0);
     61 }
     62 
     63 static int
     64 do_fd_set(struct win32op *op, struct SocketIndex *ent, SOCKET s, int read)
     65 {
     66     struct win_fd_set *set = read ? op->readset_in : op->writeset_in;
     67     
     68     if (read) {
     69         if (ent->read_pos_plus1 > 0)
     70             return (0);
     71     } else {
     72         if (ent->write_pos_plus1 > 0)
     73             return (0);
     74     }
     75 
     76     if (set->fd_count == op->num_fds_in_fd_sets) {
     77         if (grow_fd_sets(op, op->num_fds_in_fd_sets*2))
     78             return (-1);
     79         // set pointer will have changed and needs reiniting!
     80         set = read ? op->readset_in : op->writeset_in;
     81     }
     82     set->fd_array[set->fd_count] = s;
     83     if (read)
     84         ent->read_pos_plus1 = set->fd_count+1;
     85     else
     86         ent->write_pos_plus1 = set->fd_count+1;
     87     return (set->fd_count++);
     88 }
     89 
     90 static int
     91 do_fd_clear(void *base,
     92 struct win32op *op, struct SocketIndex *ent, int read)
     93 {
     94     ModelManager* pDispatcher = (ModelManager*)base;
     95 
     96     int i;
     97     struct win_fd_set *set = read ? op->readset_in : op->writeset_in;
     98     if (read) {
     99         i = ent->read_pos_plus1 - 1;
    100         ent->read_pos_plus1 = 0;
    101     } else {
    102         i = ent->write_pos_plus1 - 1;
    103         ent->write_pos_plus1 = 0;
    104     }
    105     if (i < 0)
    106         return (0);
    107     if (--set->fd_count != (unsigned)i) {
    108         struct SocketIndex *ent2;
    109         SOCKET s2;
    110         s2 = set->fd_array[i] = set->fd_array[set->fd_count];
    111 
    112         ent2 = pDispatcher->getSocketIndex( s2 );
    113 
    114         if (!ent2) // This indicates a bug.
    115             return (0);
    116         if (read)
    117             ent2->read_pos_plus1 = i+1;
    118         else
    119             ent2->write_pos_plus1 = i+1;
    120     }
    121     return (0);
    122 }
    123 
    124 #define NEVENT 32
    125 void *
    126 win32_init(void *base)
    127 {
    128     struct win32op *winop;
    129     size_t size;
    130     if (!(winop = (struct win32op*)malloc( sizeof(struct win32op))))
    131         return NULL;
    132     winop->num_fds_in_fd_sets = NEVENT;
    133     size = FD_SET_ALLOC_SIZE(NEVENT);
    134     if (!(winop->readset_in = (struct win_fd_set *)malloc(size)))
    135         goto err;
    136     if (!(winop->writeset_in = (struct win_fd_set *)malloc(size)))
    137         goto err;
    138     if (!(winop->readset_out = (struct win_fd_set *)malloc(size)))
    139         goto err;
    140     if (!(winop->writeset_out = (struct win_fd_set *)malloc(size)))
    141         goto err;
    142     if (!(winop->exset_out = (struct win_fd_set *)malloc(size)))
    143         goto err;
    144     winop->readset_in->fd_count = winop->writeset_in->fd_count = 0;
    145     winop->readset_out->fd_count = winop->writeset_out->fd_count
    146         = winop->exset_out->fd_count = 0;
    147 
    148     winop->resize_out_sets = 0;
    149 
    150     return (winop);
    151 err:
    152     XFREE(winop->readset_in);
    153     XFREE(winop->writeset_in);
    154     XFREE(winop->readset_out);
    155     XFREE(winop->writeset_out);
    156     XFREE(winop->exset_out);
    157     XFREE(winop);
    158     return (NULL);
    159 }
    160 
    161 int
    162 win32_add(void *base, SOCKET fd,
    163           short old, short events, void *_idx)
    164 {
    165     ModelManager* pDispatcher = (ModelManager*)base;
    166     struct win32op *winop = (struct win32op *)pDispatcher->getModelData();
    167     struct SocketIndex *idx = (struct SocketIndex *)_idx;
    168 
    169     if (!(events & (EV_READ|EV_WRITE)))
    170         return (0);
    171 
    172     //event_debug(("%s: adding event for %d", __func__, (int)fd));
    173     if (events & EV_READ) {
    174         if (do_fd_set(winop, idx, fd, 1)<0)
    175             return (-1);
    176     }
    177     if (events & EV_WRITE) {
    178         if (do_fd_set(winop, idx, fd, 0)<0)
    179             return (-1);
    180     }
    181     return (0);
    182 }
    183 
    184 int
    185 win32_del(void *base, SOCKET fd, short old, short events,
    186           void *_idx)
    187 {
    188     ModelManager* pDispatcher = (ModelManager*)base;
    189     struct win32op *winop = (struct win32op *)pDispatcher->getModelData();
    190     struct SocketIndex *idx = (struct SocketIndex *)_idx;
    191 
    192     //event_debug(("%s: Removing event for "EV_SOCK_FMT,__func__, EV_SOCK_ARG(fd)));
    193     if ( (old & EV_READ) && !(events & EV_READ) )
    194         do_fd_clear(base, winop, idx, 1);
    195     if ( (old & EV_WRITE) && !(events & EV_WRITE) )
    196         do_fd_clear(base, winop, idx, 0);
    197 
    198     return 0;
    199 }
    200 
    201 static void
    202 fd_set_copy(struct win_fd_set *out, const struct win_fd_set *in)
    203 {
    204     out->fd_count = in->fd_count;
    205     memcpy(out->fd_array, in->fd_array, in->fd_count * (sizeof(SOCKET)));
    206 }
    207 
    208 /*
    209 static void dump_fd_set(struct win_fd_set *s)
    210 {
    211 unsigned int i;
    212 printf("[ ");
    213 for(i=0;i<s->fd_count;++i)
    214 printf("%d ",(int)s->fd_array[i]);
    215 printf("]
    ");
    216 }
    217 */
    218 
    219 int
    220 win32_dispatch(void *base, struct timeval *tv)
    221 {
    222     ModelManager* pDispatcher = (ModelManager*)base;
    223     struct win32op *winop = (struct win32op *)pDispatcher->getModelData();
    224     int res = 0;
    225     unsigned j, i;
    226     int fd_count;
    227     SOCKET s;
    228 
    229     if (winop->resize_out_sets) {
    230         size_t size = FD_SET_ALLOC_SIZE(winop->num_fds_in_fd_sets);
    231         if (!(winop->readset_out = (struct win_fd_set *)realloc(winop->readset_out, size)))
    232             return (-1);
    233         if (!(winop->exset_out = (struct win_fd_set *)realloc(winop->exset_out, size)))
    234             return (-1);
    235         if (!(winop->writeset_out = (struct win_fd_set *)realloc(winop->writeset_out, size)))
    236             return (-1);
    237         winop->resize_out_sets = 0;
    238     }
    239 
    240     fd_set_copy(winop->readset_out, winop->readset_in);
    241     fd_set_copy(winop->exset_out, winop->writeset_in);
    242     fd_set_copy(winop->writeset_out, winop->writeset_in);
    243 
    244     fd_count =
    245         (winop->readset_out->fd_count > winop->writeset_out->fd_count) ?
    246         winop->readset_out->fd_count : winop->writeset_out->fd_count;
    247 
    248     if (!fd_count) {
    249         Sleep(tv->tv_usec/1000);
    250         return (0);
    251     }
    252 
    253 
    254     res = select(fd_count,
    255         (struct fd_set*)winop->readset_out,
    256         (struct fd_set*)winop->writeset_out,
    257         (struct fd_set*)winop->exset_out, tv);
    258 
    259 
    260     //event_debug(("%s: select returned %d", __func__, res));
    261 
    262     if (res <= 0) {
    263         if( res == -1 )
    264         {
    265             printf("error:%d
    ", getErrno() );
    266         }
    267         return res;
    268     }
    269 
    270     if (winop->readset_out->fd_count) {
    271         i = rand() % winop->readset_out->fd_count;
    272         for (j=0; j<winop->readset_out->fd_count; ++j) {
    273             if (++i >= winop->readset_out->fd_count)
    274                 i = 0;
    275             s = winop->readset_out->fd_array[i];
    276             pDispatcher->insertActiveList( s, EV_READ);
    277         }
    278     }
    279     if (winop->exset_out->fd_count) {
    280         i = rand() % winop->exset_out->fd_count;
    281         for (j=0; j<winop->exset_out->fd_count; ++j) {
    282             if (++i >= winop->exset_out->fd_count)
    283                 i = 0;
    284             s = winop->exset_out->fd_array[i];
    285             pDispatcher->insertActiveList( s, EV_WRITE);
    286         }
    287     }
    288     if (winop->writeset_out->fd_count) {
    289         SOCKET s;
    290         i = rand() % winop->writeset_out->fd_count;
    291         for (j=0; j<winop->writeset_out->fd_count; ++j) {
    292             if (++i >= winop->writeset_out->fd_count)
    293                 i = 0;
    294             s = winop->writeset_out->fd_array[i];
    295             pDispatcher->insertActiveList( s, EV_WRITE);
    296         }
    297     }
    298     return (0);
    299 }
    300 
    301 void
    302 win32_dealloc(void *base)
    303 {
    304     ModelManager* pDispatcher = (ModelManager*)base;
    305     struct win32op *winop = (struct win32op *)pDispatcher->getModelData();
    306 
    307     if (winop->readset_in)
    308         free(winop->readset_in);
    309     if (winop->writeset_in)
    310         free(winop->writeset_in);
    311     if (winop->readset_out)
    312         free(winop->readset_out);
    313     if (winop->writeset_out)
    314         free(winop->writeset_out);
    315     if (winop->exset_out)
    316         free(winop->exset_out);
    317 
    318 
    319     memset(winop, 0, sizeof(winop));
    320     free(winop);
    321 }
    322 
    323 #endif


    到此总结完毕,关注我的公众号

     


     

  • 相关阅读:
    Asp.net把UTF-8编码转换为GB2312编码
    润乾报表中文传参乱码的问题
    润乾报表中填报中文出现乱码
    SQL Developer不能删除和复制及部分键失效问题
    .NET类型转换的常用方式
    .net中三种数据类型转换区别((int),Int32.Parse() 和 Convert.toInt32() )
    什么是SFP光模块?
    什么是"双活"
    存储软件特性
    【分享】给自己的博客园添加一个板娘(可选)
  • 原文地址:https://www.cnblogs.com/secondtonone1/p/5822436.html
Copyright © 2020-2023  润新知