首页 > 代码库 > 网络编程一些常见问题总结

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

1 设置网络socket非阻塞:

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

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

总结如下:

 

intmake_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         else119             ent2->write_pos_plus1 = i+1;120     }121     return (0);122 }123 124 #define NEVENT 32125 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_count146         = 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 int162 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 int185 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 void202 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("]\n");216 }217 */218 219 int220 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\n", 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 void302 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


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

 

 

 技术分享

 


 

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