Linux网络编程实验——进程池实现服务器

  这是学习Linux网络编程以来的第一个相对比较长的实验。途中遇到了许多乱七八糟的问题以致感觉自己迷迷糊糊的,所以打算把这些记下来算作梳理。

  实验取自《Linux高性能服务器编程》15.3节

  代码已经全部上传到我的github仓库,文后附上链接。

Something interesting

1.不像使用pipe()创建的管道两边只能一个读一个写,socketpair第一个参数选用PF_UNIX打开的“管道”两边是可读写的。并且这两段任意一个被关闭都会向对端发送信息使其接收函数的返回值为0.

int socketPairRet = socketpair(PF_UNIX, SOCK_STREAM, 0, m_subProcess[i].m_pipeFd);

2.尽量使用epoll的边沿触发,不仅效率高而且减少了很多的麻烦!看到下面的epoll_wait和send没有,这里的操作是父进程收到了客户端连接之后通知子进程进行处理。由于我使用了默认的水平触发所以在send发送完了之后又回到epoll_wait,然后如此多次循环往复,不仅让中间的轮训调度算法,更是其它部分的代码也白白执行了很多次,搞到最后的调度结果也是一团糟糕。更加恶心的是,由于之前的疏忽我把socketpair产生的父子进程通信的管道一段给关闭了,然后没有关闭的一段产生了许多的读消息,epoll_wait就在这里疯狂循环,目前我还没能知道该怎么处理掉这个读事件。

Linux网络编程实验——进程池实现服务器_第1张图片
3.在memset和recv这两个函数上面吃了亏.
先来看第一个recv。作者书上的signals数组定义的是char类型,但因为传送的signal类型的明明是int所以我不以为然硬是把这里的signals也设置成了int。蛋疼的情况马上出现,明明只传递了一个信号可打上的printf却显示我发送了四个信号。。。仔细研究才发现recv返回的是收到的字节数。
类似的错误也放在了memset,这个函数的第三个参数表示的是被设置的空间区域字节数是多少但被我当成了被设置的数组大小。

retNum = recv(sigPipeFd[0], signals, MAX_SIGNAL_NUMBER, 0);
memset(clientFds, 0, MAX_CLIENT_NUMBER * sizeof(int));

4.还有最最重要的一点!
我真的应该找时间把这些网络相关的函数封装起来留给以后使用!!!
终于体会到这种系统接口琐碎带来的麻烦!!!
不仅在写的时候需要额外考虑特殊情况会打断原有思路,而且更重要的是一遍又一遍的重复劳动让人非常烦躁!!!

之后自用的封装函数也会放在这个git仓库中

你可能感兴趣的:(Linux网络编程实验——进程池实现服务器)