Android网络编程——Socket

一 前言

在之前的文章中有提过Socket(作为进程间通信的一种方式),其实Socket是封装了底层的TCP和UDP协议,为开发者提供的友好网络编程接口(注意是个编程库,不是协议),对开发者而言是网络编程的重要知识点。要了解Socket我们先从网络的基础知识讲起,看看Socket在网络模型中的位置。

二 网络基础知识

20世纪70年代Vinton Gray Cerf(文顿·瑟夫)和Robert Elliot Kahn(罗伯特·卡恩)两位先生设计了TCP/IP协议模型,奠定了现代网络的基础知识。这世上从来就没有什么理所当然就存在的事情,感谢先辈们的付出,向他们致敬。后来又经过分层设计,演变成了现在的四层模型(自上而下分为应用层、传输层、网络互联层和网络接口层)。这个四层协议模型为业界所通用,但不知道什么原因国际化标准组织搞了一个七层的OSI组织模型,这个七层模型层数太多,遭到很多专家反对,其中普度大学的教授Douglas Comer(先生在网络界的盛名不需多说)这样批评这个七层模型(下面是引用WolfcsTec翻译的教授文章原话)

研究人员开始回顾 OSI 七层参考模型的起源,琢磨这个笨重的、模糊不清的模型为什么如此的持久,总是挥之不去。他们发现了一个令人吃惊的事实。我们早就知道,这个模型是一个小组(国际化标准组织)的工作,但是我们不知道,那群人在一天夜里聚在酒吧里取笑美国的流行文化。他们在餐巾纸上胡乱写下迪斯尼电影《白雪公主和七个小矮人》中的七个小矮人的名字。有人开玩笑说,“7”对网络分层来讲是一个很好的数字。第二天上午在标准化委员会的会议上,工作组传看着餐巾纸,一致同意了他们前天夜里喝醉以后的重大发现。那天结束时,他们对七个层次重新命名(听起来更加科学),于是基本模型诞生了。以下罗列了七层的名字和一些解释:
层次 小矮人的名字 OSI分层的名字 解释
1 Sleepy Physical(物理层) . . . . . .
2 Sneezy Link (链路层) . . . . . .
3 Happy Network(网络层) . . . . . .
4 Doc Transport(传输层) . . . . . . .
5 Dopey Session(会话层) . . . . . .
6 Bashful Presentation(表示层) . . . . . .
7 Grumpy Application (应用层) . . . . . .
这个故事的教训:如果你是一个标准委员会的工程师,就不要和你的同事去喝酒——深夜里一个拙劣的笑话,有可能成为工业界几十年都挥之不去的梦魇。

好吧,教授这段话,诛心之论,那还说什么,我们就看看计算机的四层TCP/IP网络模型。

2.1 TCP/IP协议模型

废话不多说,先上一张我画的图


TCP/IP四层模型.jpg

以应用层的Http协议简单解释这四层

  • 应用层:用户在浏览器输入一个"http://"开头的url地址后,浏览器会根据网址的含义,生成HTTP请求消息。然后把消息向下转交给传输层。
  • 传输层:传输层按照网络数据包的长度对数据拆分,在每个包前面加上TCP头部并向下转交给网络互联层(IP层)。
  • 网络互联层:网络互联层在TCP包的前面加上IP头部,然后向下转交给接口层。
  • 网络接口层:如果是以太网络时,会查询MAC地址,并加上MAC头部,向下转交给网卡驱动。

2.2 网络数据传输流程

上面说了TCP/IP协议的四层模型,好像没看到Socket(这说明他确实不是一个协议),接下来梳理网络数据传输的流程。先看自己梳理的一张网络数据在客户端/服务端之间的数据传输图。


网络数据传输.jpg

流程很清晰,就不在多说,说几个关注点:

  • 请求方,数据打包,并层层加头部向下传递;
  • 接收方,数据向上层层解析;
  • 在应用层生成数据后,会通过调用Socket库委托系统协议栈(TCP/IP协议)发送和接受数据;
  • Scoket库封装了TCP或者UDP协议;

下面先看看TCP和UDP协议连接流程。

2.3 TCP协议

TCP是一种面向连接、面向字节流、全双工通信、可靠的协议。

2.3.1 TCP连接

先看一下TCP连接过程(也就是传说中的"三次握手"),如下图:


TCP三次握手.jpg

这里引用林沛满的一段解释(很形象):

客户端:“我能和你建立连接吗?我的初始发送序号是X。如果你答应就Ack=X+1。”
服务端:“收到,Ack=X+1。我也想和你建立连接。我的初始序号是Y,你如果答应就Ack=Y+1。”
客户端:“收到,Ack=Y+1。”

注意上面的SYN标识正在发起连接。上面三次握手完成了TCP的连接。
为什么要搞三次这么复杂,两次不行吗。两次不可靠,后面会补上为什么两次不可靠的原因。

2.3.2 TCP断开

后续加上

2.4 UDP协议

UDP协议无需连接,数据发出去就不管了。另外,UDP传输的数据包相比较TCP而言,量很少。最典型的应用场景就是DNS查询。

三 Socket

上面说了Socket是封装了TCP或者UDP协议,提供给开发者的编程接口库。
其实就实现了上面讲的TCP协议和UDP协议原理。
一般Socket使用的几个步骤:

  • 创建Socket。
  • 连接阶段(将管道连接到服务器)。
  • 通信阶段(通信阶段)。
  • 断开阶段(断开连接管理,并删除套接字)。
    // 1.创建Socket对象,并指定连接服务端的IP及端口号 ,连接。
    Socket socket = new Socket("192.168.0.100", 8001);  
    // 判断客户端和服务器是否连接成功  
    socket.isConnected());

    // 2.通信阶段
            //创建输入流对象InputStream
            InputStream is = socket.getInputStream() 
            // 解析服务端返回数据
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            //读取解析后的数据
            br.readLine();
      
            // 从Socket 获得输出流对象OutputStream
            OutputStream outputStream = socket.getOutputStream(); 
            // 写入需要发送的数据到输出流对象中
            outputStream.write("test").getBytes());
            // 发送数据到服务端 
            outputStream.flush();  
      // 3.断开阶段
            os.close();
            // 断开 客户端发送到服务器 的连接,即关闭输出流对象OutputStream
            br.close();
            // 断开 服务器发送到客户端 的连接,即关闭输入流读取器对象BufferedReader
            socket.close();
            // 最终关闭整个Socket连接

当然也需要服务端配合。
代码地址(利用BIO模式实现):
Client端
Server 端

参考文章

[1] Wireshark网络分析就这么简单.林沛满
[2] 网络是怎样连接的.户根勤
[3] 鸟哥的Linux私房菜
重点推荐《网络是怎样连接的》这本书,本人还没看完,作者从软件到硬件,从服务器到交换机,每一方面都在行,而且文字功底好。
由于本人能力有限,有的方面理解不当,后续会根据情况继续调整。

你可能感兴趣的:(Android网络编程——Socket)