Browsed by
分类:计算机网络

Linux 下C语言简单echo server的实现

Linux 下C语言简单echo server的实现

本文为 高性能网络编程学习 系列文章的第0篇

本文目的为讲述简单的echo server的实现, echo server的含义如字面意思, 客户端发送什么数据,服务器就返回什么数据作为响应,本系列文章的目的不在于实现复杂的服务器端业务逻辑,在于学习如何开发出高性能的网络通信程序,因而所有的代码均为echo server的实现

Linux下用C进行网络通信的话, 需要使用socket, 即Linux socket interface, socket是一种IPC(Inter Process Communication进程间交互)的方式,同时socket还可以允许跨host,即在不同的主机上的进程之间进行通信,在Linux上,所有的IO操作都是通过对文件的写入读出实现的,socket也作为一种文件存在,可以通过read, write进行IO

客户端我们采用的是一个benchmark程序,即1000个client,每一个client发送1000个请求,客户端为了简洁和快速编写,使用golang开发,之后所有的server都使用这个benchmark进行测试,代码如下

客户端程序不进行赘述,我们下面实现服务器端,通过socket监听一个端口并且与客户端进行读写交互有以下几个关键步骤

  1. socket创建
  2. 将socket绑定到指定的地址和端口
  3. 将socket变为listen状态
  4. 通过accept接受来自客户端的链接
  5. read/write与客户端进行交互

本例我们实现的是一个单进程的echo server, 下面是server的代码

如果是第一次写socket通信的代码,有几个地方容易卡住,下面把上述代码中几个比较容易出错和忘记的地方注明一下

整体流程

  • Create socket的时候使用socket()函数,具体用法查看man page,关于domain, protocol family的指定,man page中说的是“implementation-defined”想要找到所有的定义,Linux下需要查看 bits/socket.h文件
  • sockaddr_in 这个结构体用于表示internet (IPV4)的address, 这里使用的是sockaddr_in而不是sockaddr
  • 使用bind的时候注意addr结构体为sockaddr*,我们使用的是sockaddr_in需要进行类型转换,不用担心转换数据丢失或者错乱,这些结构体在实现的时候就已经假定用户使用时一定会用到强制类型转换的
  • bind之后,我们通过listen,使这个socket变为可以接受外界链接的状态
  • listen之后通过accept接受client的链接,每一个client都会产生一个新的文件以及fd,只需要对这个fd进行读写,就可以实现client和server的交互了
  • accept的时候需要注意一点,accept的参数中传递的socket应该为用于listen的socket,这个socket可以accept多个连接,accept返回的文件描述符对应的文件虽然也是一个socket,不过不可以用于accept多个连接,应该再这个链接断开时关闭掉相应的fd

关于sockaddr_in的参数以及初始化

  • 对于sockaddr_in结构体的addr的指定,指定其监听所有网卡的最常用的方式是 htonl(INADDR_ANY) 注意这里一定要用htonl来进行不同机器的兼容性转换,网络上的机器的架构,数据表示均不同,为了让数据能够在各个机器上被正确解读,我们需要用到几个宏(函数)对数据进行转换,具体参考man page byteorder,  这里的数据INADDR_ANY为一个长整型,因而使用htonl进行转换
  • 另外在多说一句htonl等一系列函数的记忆方法,他的全称就是 Host TO Network Long, 其他的htons ntohl这些就都可以记住了不会搞混
  • 关于addr以及port为什么要转换为network上的binary数据呢, 原因很简单,因为这些数据要在网络上传递,因此我们就需要做这个转换咯

运行性能测评

使用benchmark工具运行代码参数如下

运行结果为

 

运行在4C 8G 的ArchLinux上 可以看到有很多链接失败,日志里的原因为connection refused,完成1000个client的通信共用3min40秒,因而这种单进程单链接的代码是没有任何实际工程意义的(废话)

 

计算机网络的体系结构(Computer Network Architecture)

计算机网络的体系结构(Computer Network Architecture)

计算机网络的体系结构

几个重要概念: 接口 服务 协议

哲学家模型:

[哲学家模型的图片]

哲学家模型体现了两个重要的问题:

  • 不同系统的对等层(peer layer)之间(秘书1与秘书2 翻译1与翻译2)存在协议   同一系统的上下层之间(哲学家1 与翻译1 , 翻译1 与 秘书1 )是服务和被服务的关系,不存在协议,服务的调用通过两层之间的接口进行
  • 保持对上下层提供的服务不变的前提下, 对等层的协议可任意规定(如 两个翻译家可以都使用Spanish或者都使用Dutch进行交流 不影响哲学家收到正确的信息)

计算机网络的体系结构

1.ISO提出的 OSI/RM 七层结构

[七层结构图]

空间 - 1

2.TCP/IP RM 结构

[五层结构图]

空间 - 2

每一层的作用:

  • 应用层: 提供各种应用程序服务
  • 传输层:保证报文能够正确,按序到达
  • 网络层:路由
  • 网络硬件, 后来分为两层:
    • 数据链路层: 比特差错校验
    • 物理层: 实现透明的比特传输