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

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

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

时间: 2024-10-19 00:49:42

网络编程一些常见问题总结的相关文章

【转】网络编程常见问题总结

网络编程常见问题总结 这里对在网络程序中遇到的一些问题进行了总结, 这里主要针对的是我们常用的TCP socket相关的总结, 可能会存在错误, 有任何问题欢迎大家提出. 对于网络编程的更多详细说明建议参考下面的书籍 <UNIX网络编程> <TCP/IP 详解> <Unix环境高级编程> < div> 网络编程常见问题总结 相关说明 非阻塞IO和阻塞IO 基本概念 设置 区别: 读: 写: 超时控制: 长连接和短连接的各种可能的问题及相应的处理 短连接: 长

《网络编程》

<网络编程> 作者:冯皓林 完稿:2016.1.2x--2016.2.X WHAT?什么是网络编程? 网络编程解决的是计算机之间的数据传输问题. 区别: 网页编程:基于html页面(网页)客户端与服务端进行数据传输.(servlet.html.css等) 计算机网络:计算机网络就是指分布在不同地域的计算机通过外部设备连接起来,以达到了互相通讯或者是资源共享的功能. 网络模型: OSI(Open System Interconnection开放系统互连)参考模型: TCP/IP参考模型(沙漏模型

网络编程泛谈

本文目的在于整理一下网络编程过程中问题,旨在加深自己的理解,同时也供读者参考. 参考书:<UNIX网络编程> 从以下几个方面进行介绍: 网络编程的基础知识(TCP/IP协议) TCP客户端/服务器(echo服务)例子 高效的网络编程:阻塞/非阻塞,同步/异步,IO复用(select/poll/epoll学习,跨平台封装的库libev) 非阻塞+IO复用的echo服务 网络开发中的master/worker编程模型:Nginx/Uwsgi(这里再讨论下惊群问题) 多进程+非阻塞+IO复用的ech

java进阶学习 --java网络编程一(转)

Java - 网络编程完全总结(基础介绍) 本文主要是在网络编程方面的学习总结,先主要介绍计算机网络方面的相关内容,包括计算机网络基础,OSI参考模型,TCP/IP协议簇,常见的网络协议等等,在此基础上,主要介绍Java中的网络编程. 目录 一.概述 二.计算机网络 1.网络协议 2.网络体系结构 三.OSI参考模型 四.TCP/IP参考模型 五.常见网络协议 1.TCP协议 2.UDP协议 3.HTTP协议 六.计网常见问题 一.概述 计算机网络是通过传输介质.通信设施和网络通信协议,把分散在

也谈服务器端网络编程

这里主要说一下自己看的书和一些心得体会,把自己的学习路线梳理一下,也是作为自己这段时间的学习总结. 因为从事的都是服务器端开发和学习,所以本文内容主要在该范围内,假定读者经过了系统的CS学习(DS.OS.组成原理等核心课程). First,我的学习书籍路线参考如下内容: 1 A:<Linux鸟哥私房菜>(第三版): 2 3 B:<Linux程序设计>(第四版 中文版): 4 5 C:<TCP/IP详解v1>(英文版): 6 7 D:C/C++语言相关: 8 9 E:&l

《Go语言网络编程》第一章:体系

原书地址:http://tumregels.github.io/Network-Programming-with-Go 如果不知道想要构建什么,是不可能创建一个系统的.而且如果不知道它工作的环境,也同样无法构建. GUI程序不同于批处理程序:游戏程序不同于商业程序:分布式程序不同于单机程序. 他们都有自己的方法.一般模式和问题,都有各自的常见问题和常见解决方案. 本章讨论分布式系统高层架构层面的一些内容.有多种方式看待这样的系统,而且其中的许多问题已经被解决. 协议层 分布式系统很难!其中涉及到

java大神必学篇之网络编程完全总结

本文主要是自己在网络编程方面的学习总结,先主要介绍计算机网络方面的相关内容,包括计算机网络基础,OSI参考模型,TCP/IP协议簇,常见的网络协议等等,在此基础上,介绍Java中的网络编程. 一.概述二.计算机网络1.网络协议2.网络体系结构三.OSI参考模型四.TCP/IP参考模型五.常见网络协议1.TCP协议2.UDP协议3.HTTP协议六.计网常见问题七.Java网络编程一.概述 计算机网络是通过传输介质.通信设施和网络通信协议,把分散在不同地点的计算机设备互连起来,实现资源共享和数据传输

Java网络编程和NIO:Java网络编程基础

转自: https://www.cnblogs.com/midiyu/p/7875574.html 关于网络 网络协议 如同人与人之间相互交流是需要遵循一定的规矩一样,计算机之间能够进行相互通信是因为它们都共同遵守一定的规则,即网络协议. 网络体系结构 计算机网络是个复杂的系统,按照人们解决复杂问题的方法,把计算机网络实现的功能分到不同的层次上,层与层之间用接口连接.通信的双方具有相同的层次,层次实现的功能由协议数据单元(PDU)来描述.不同系统中的同一层构成对等层,对等层之间通过对等层协议进行

C#网络编程技术FastSocket实战项目演练

一.FastSocket课程介绍 .NET框架虽然微软提供了socket通信的类库,但是还有很多事情要自己处理,比如TCP协议需要处理分包.组包.粘包.维护连接列表等,UDP协议需要处理丢包.乱序,而且对于多连接并发,还要自己处理多线程等等.本期分享课程阿笨给大家带来的是来源于github开源Socket通信中间件:FastSocket,目的就是把大家从繁琐的网络编程技术中彻底地解放和释放出来. 阿笨只想安安静静的学习下网络编程技术Socket后,将学习的成果直接灵活的运用到自己的实际项目中去.