PHP 网络编程小白系列 —— 初探

这篇文章我打算先丢出一个引子来引起各位读者对于网络思考,然后慢慢聊到网络连接的程序,这跟socket 又有什么关系,操作 socket 时我们需要了解的通信规则以及通信数据会产生的几种状态例如:同步、异步、死锁、解锁、阻塞。

引子 —— 网络是怎么连接的?

有一个经典的问题:当你在浏览器输入一个网址后,你是如何获取到了想要的内容,这其中发生了什么?

如果要完整的回答这个问题,恐怕写一本书都不算多,这里大致说说有几个环节和里面的点:

1.浏览器会根据通信协议解析 uri 生成请求消息
2.浏览器访问 DNS 服务器解析请求 uri 为 ip 地址
3.浏览器调用 socket 库委托操作系统中的协议栈发送请求消息
4.网卡将数字信号转换为电信号输出网线
5.交换机将电信号再次转换为数字信号
6.解包
7.根据 socket 控制信息(ip、端口、状态)到达应用程序

上面有几个注意的问题:

a. 1、2 顺序不能颠倒,网上有说先 DNS 解析是错误的
b. 库就是一组程序的集合,socket 库是让其他应用可以使用操作系统的网络功能
c. 协议栈包括 Tcp、Udp、Ip、Arp...各种协议

可以看到一个简单的网络连接是需要很多网络部件参与才能正常工作,我们主要关心第三步的实现即这个 socket 程序组件的运用,对于开发者来说这个 socket 是网络连接的关键也是我们网络编程的关键。

什么是网络编程?

一句话: 通过 coding 实现网络通信的的行为

什么是 socket?

一句话: 收发通信数据的管道(请求|响应消息都要通过 socket)

你可能还需要了解的东西?

有些东西在网络连接过程中我们是看不到的或者说在编写程序的时候不会直接使用,但是在实际编写网络程序的时候我们必须遵守其中的规则,所以我们还是很有必要了解的。

TCP 三次握手和四次挥手

  • socket 连接的时候就是在握手哈

先看一个有趣的解释:

我们举一个现实生活中两个人进行语言沟通的例子来模拟三次握手。
第一次对话:
老婆让甲出去打酱油,半路碰到一个朋友乙,甲问了一句:哥们你吃饭了么?
结果乙带着耳机听歌呢,根本没听到,没反应。甲心里想:跟你说话也没个音,不跟你说了,沟通失      败。说明乙接受不到甲传过来的信息的情况下沟通肯定是失败的。
如果乙听到了甲说的话,那么第一次对话成功,接下来进行第二次对话。
第二次对话:
乙听到了甲说的话,但是他是老外,中文不好,不知道甲说的啥意思也不知道怎样回答,于是随便回答了一句学过的中文 :我去厕所了。甲一听立刻笑喷了,“去厕所吃饭”?道不同不相为谋,离你远点吧,沟通失败。说明乙无法做出正确应答的情况下沟通失败。
如果乙听到了甲的话,做出了正确的应答,并且还进行了反问:我吃饭了,你呢?那么第二次握手成功。
通过前两次对话证明了乙能够听懂甲说的话,并且能做出正确的应答。接下来进行第三次对话。
第三次对话:
甲刚和乙打了个招呼,突然老婆喊他,“你个死鬼,打个酱油咋这么半天,看我回家咋收拾你”,甲是个妻管严,听完吓得二话不说就跑回家了,把乙自己晾那了。乙心想:这什么人啊,得,我也回家吧,沟通失败。说明甲无法做出应答的情况下沟通失败。
如果甲也做出了正确的应答:我也吃了。那么第三次对话成功,两人已经建立起了顺畅的沟通渠道,接下来开始持续的聊天。
通过第二次和第三次的对话证明了甲能够听懂乙说的话,并且能做出正确的应答。
可见,两个人进行有效的语言沟通,这三次对话的过程是必须的。

同理,连接拆除时需要两方都确定才能真正拆除,所以需要四次挥手

再具体看看图示:

TCP 协议创建
  • 客户端主动调用 connect 发送 SYN 分节
  • 服务器端必须回复一个 ACK 分节来确认客户端 SYN 分节,并发送一个 SYN 分节到客户端
  • 客户端对服务器端发送的 SYN 分节进行 ACK 确认

wm

TCP 协议拆除
  • 首先申请拆除的一端调用 close 发送一个 FIN 分节
  • 另一端接收到 FIN 分节时,发送一个 ACK 分节进行确认
  • 同理,另一端要申请拆除连接时,也要发送一个 FIN 分节
  • 接收端发送 ACK 分节进行确认

wm

阻塞/非阻塞

这两个概念是针对 IO 过程中进程的状态来说的,阻塞 IO 是指调用结果返回之前,当前线程会被挂起;相反,非阻塞指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。

同步/异步

这两个概念是针对调用如果返回结果来说的,所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回;相反,当一个异步过程调用发出后,调用者不能立刻得到结果,实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者。

I/O 多路复用

多路复用(IO/Multiplexing):为了提高数据信息在网络通信线路中传输的效率,在一条物理通信线路上建立多条逻辑通信信道,同时传输若干路信号的技术就叫做多路复用技术。对于 Socket 来说,应该说能同时处理多个连接的模型都应该被称为多路复用,目前比较常用的有 select/poll/epoll/kqueue 这些 IO 模型(目前也有像 Apache 这种每个连接用单独的进程/线程来处理的 IO 模型,但是效率相对比较差,也很容易出问题,所以暂时不做介绍了)。在这些多路复用的模式中,异步阻塞/非阻塞模式的扩展性和性能最好。

参考链接语扩展阅读

改变世界的TCP/IP协议
What is socket?
《网络是怎么连接的》

初探结语

简单说明网络编程就是利用 socket 程序组件实现网络连接的,在具体操作 socket 的时候会涉及一些额外的知识点,整篇文章很简单没有深入探究某个点,自然也不会很完备,这也是对本系列文章的定位,之后写网络通信模型的时候会结合具体例子来阐述涉及到的知识点。下一节主要结合 PHP 介绍一下 socket 的相关函数。

阅读 512更新于 2018-07-24
推荐阅读
目录