套接字编程(三)

1.4k 词

服务器软件设计概述

最简单服务器的算法

  1. 创建套接字
  2. 绑定到一个熟知端口
  3. 期望在这个端口上接受请求
  4. 进入无线循环,接收客户请求并应答

循环与并发

  • 循环服务器:一个时刻只处理一个请求
    • 易构建,性能稍差
  • 并发服务器:一个时刻可以处理多请求
    • 多数只提供表面并发:执行多个线程,每个线程处理一个请求
    • 使用线程的可能性:计算量小,主要是异步I/O,便于同时使用多个通信信道
    • 并发处理多个请求,而不是指下层使用了多个并发线程
    • 难以构建,性能好

面向连接和无连接的访问

  • TCP/IP提供了两种协议
    • 使用TCP的服务器是面向连接的服务器
      • 点到点通信
      • 建立可靠连接
      • 可靠交付
      • 具有流控的传输
      • 双工传输
      • 流模式
    • 使用UDP的服务器是无连接的服务器
      • 多对多通信
      • 不可靠服务
      • 缺乏流控制
      • 报文模式
  • 选择面向连接或者无连接的服务依赖于应用协议

面向连接

  • 易于编程
    • 自动处理分组丢失,分组失序
    • 自动验证数据差错,处理连接状态
  • 对每个连接都有一个单独的套接字,耗费更多资源
  • 在空闲的连接上不发送任何分组
  • 始终运行的服务器会因为客户的崩溃,导致无用套接字的过多而耗尽资源

无连接

  • 没有资源耗尽问题
  • 需要自己完成可靠通信问题
    • 必要时,需要一种自适应重传的复杂技术
    • 对于可靠通信场合,尽量使用TCP
  • 是否需要组播或者广播是考虑何种传输方式的因素
    • 支持组播或者广播的服务器必须是无连接的

四种基本类型服务器

  • 循环的或者并发的
  • 面向连接的或无连接的

循环服务器算法

  • 循环服务器设计、编程、排错、修改很容易,往往使用无连接的协议
  • 循环服务器对于小的处理时间的服务工作很好
  • TCP面向连接的循环服务器算法
    • 创建套接字并将其绑定到它所提供服务的熟知端口上
      • getservbyname:服务器名映射到熟知端口上
      • bind:为某个套接字指明端点,使用结构sockaddr_in,该结构包含有IP地址和端口号
      • 对于多接口主机使用INADDR_ANY指明一个通配地址,让该主机的任何一个IP地址都能匹配
    • 将该端口设置为被动模式,使其准备为服务器所用
      • 调用listen将套接字置于被动模式
      • 接收并使用连接
      • 调用accept获得下一个传入连接请求
    • 从该套接字上接收下一个连接请求,获得该连接的新的套接字
    • 重复地读取来自客户的请求,构造响应,按照应用协议向客户发回响应
    • 当某个特定客户完成交互时,关闭连接,并返回步骤三以接收新的连接
  • 无连接循环服务器
    • 创建套接字并将其绑定到所提供服务的熟知端口上
    • 重复读取来自客户的请求,构造响应,按照应用协议向客户发回响应
      • sendto:指明发送的数据报和它将去的地址
      • 服务器从收到的请求中的源地址获得应答地址。调用recvfrom得到数据和对方的地址

并发服务器

  • 给多个用户提供快速响应时间需要使用并发服务器
  • 尽管可以使用一个单线程实现并发服务器,但是大多数使用多线程
  • 并发无连接服务器算法
    • 主:创建套接字并将其绑定到提供服务的熟知地址上,让该套接字保持未连接
    • 主:反复调用recvfrom接收来自客户的下一个请求,创建一个新的从线进程来处理响应
    • 从:从来自主进程的特定请求以及到该套接字的访问开始
    • 从:根据应用协议构造应答,并用sendto将该应答发回给客户
    • 从:退出
  • 面向连接的服务器在多个连接之间实现并发
    • 主:创建套接字并将其绑定到所提供服务的熟知端口上,让该套接字保持为面向连接
    • 主:将该端口设置为被动模式
    • 主:反复调用accept以便接收来自客户的下一个连接请求,并创建新的从线程或者进程来处理响应
    • 从:由主线程传递来的连接请求开始
    • 从:用该连接与客户进行交互,读取请求并发回响应
    • 关闭连接并退出
留言