zoukankan      html  css  js  c++  java
  • tcp服务器端设计

    要求:此服务器是个并发服务器,能同时服务多个客户

    解决方案:调用fork(),生成子进程,让每个子进程服务于一个客户

    导致的潜在问题:子进程退出后会变成僵尸进程,占用内存空间,要求父进程调用wait()来处理,但不能同步调用wait(),因为这会导致无法实现并发

    解决方案:采用信号机制,异步调用wait(),当子进程退出时,内核会像其父进程发送一个SIGCHLD信号,因此我们注册一个信号处理函数,当收到SIGCHILD信号时捕获这个信号并调用wait(),这又带来了一个新问题

    潜在问题:进程收到信号并调用信号处理函数时会中断正在运行的系统调用,有些系统在处理完信号后并不重新启动被中断的系统调用,这就要求我们自己启动

    潜在问题:当父进程在同一时刻收到多个SIGCHLD信号或信号阻塞期间收到多个SIGCHLD时,他只调用一次信号处理函数,这就导致了有未被及时处理的子进程

    解决方案:采用waitpid(),非阻塞方式循环处理,如果有僵尸子进程则处理,如果没有则循环结束

    处理可能发生的异常情况

    异常情况1:服务器端子进程被关闭

    服务器端行为:给客户端发送一个FIN

    客户端情况:客户进程此时阻塞于fgets()函数,不知道服务器子进程已经关闭。tcp协议栈收到FIN,tcp协议栈认为对方单项关闭,仍可向对方发送数据,允许调用write()函数,并能成功返回,都是协议栈的锅,收到FIN只能代表对方已经单项关闭,无法知道服务器子进程已经关闭,即全关闭,这就导致了客户端不能立即知道服务器子进程已经关闭,当调用read()时,read()会返回0,此时客户端才知道服务器子进程已关闭。

    此情况发生时write()函数的情况:tcp协议栈收到FIN,tcp协议栈认为对方单项关闭,仍可向对方发送数据,允许调用write()函数,并能成功返回,此时由于服务器子进程已关闭,tcp协议栈会发送一个RST给客户端,但客户端进程不知道这个过程,若收到RST后再次调用writen(),内核会向客户进程发送SIGPIPE信号,进程会被终止

    解决办法:就本程序而言,认为read()返回0时就代表不能向服务器发送数据,一旦收到FIN,read()就会返回0,但当收到FIN时,客户端阻塞于fgets(),解决此问题的办法是使用select()

    处理被中断的系统调用:系统阻塞于某个系统调用时若收到信号,系统调用会被中断返回,erron会被设置为EINTR,此时需要我们自行重新调用被中断的函数

    服务器端服务函数的设计

    不同的服务器有不同的服务函数,但一般首先都是要读取套接字数据,再根据服务要求处理数据,并将处理结果返回给客户,客户可能要求多次服务,所以服务函数应该设计为被动退出,采用循环,read()返回0代表客户端不再发送请求,循环结束,此时服务函数方可返回

  • 相关阅读:
    经典网页设计:漂亮的个人作品集网站设计欣赏【中篇】
    引领网页设计潮流的优秀网页作品赏析《第二季》
    Chance – 功能强大的 JavaScript 随机数生成类库
    设计前沿:16款扁平风格 iOS 7 图标设计
    TwentyTwenty – 使用 jQuery 实现图片对比功能
    未来的 Web:九个不可思议的 WebGL 应用试验
    推荐25个帮助你提高技能的 CSS3 实战教程
    经典网页设计:顶尖的个人作品集网站设计欣赏【上篇】
    Smint – 用于单页网站制作的 jQuery 导航菜单插件
    关注经典:CSS Awards 获奖网站作品赏析《第一季》
  • 原文地址:https://www.cnblogs.com/adelep/p/6904779.html
Copyright © 2011-2022 走看看