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("]\n"); 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\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 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
到此总结完毕,关注我的公众号