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代表客户端不再发送请求,循环结束,此时服务函数方可返回

  • 相关阅读:
    IE浏览器下报错: strict 模式下不允许一个属性有多个定义
    Vue 做的项目在IE下面打开一片空白解决方法
    小程序如何动态修改标题navigationBarTitleText
    小程序-for循环遍历的使用
    vue项目-打印页面中指定区域的内容(亲测有效!)
    vue省市区三级联动(高仿京东)
    vue-父组件向子组件传值
    Sea.js 手册与文档
    angular之模块开发二
    angular之跨域
  • 原文地址:https://www.cnblogs.com/adelep/p/6904779.html
Copyright © 2011-2022 走看看