首页 > 代码库 > 网络编程一些常见问题总结
网络编程一些常见问题总结
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 对应文件 " 就可以解决这个问题。
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
到此总结完毕,关注我的公众号
网络编程一些常见问题总结