LV06-03-网络编程-01-socket基础

本文主要是网络编程——socket基础知识的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。

点击查看使用工具及版本
Windows windows11
Ubuntu Ubuntu16.04的64位版本
VMware® Workstation 16 Pro 16.2.3 build-19376536
SecureCRT Version 8.7.2 (x64 build 2214) - 正式版-2020年5月14日
开发板 正点原子 i.MX6ULL Linux阿尔法开发板
uboot NXP官方提供的uboot,NXP提供的版本为uboot-imx-rel_imx_4.1.15_2.1.0_ga(使用的uboot版本为U-Boot 2016.03)
linux内核 linux-4.15(NXP官方提供)
STM32开发板 正点原子战舰V3(STM32F103ZET6)
点击查看本文参考资料
参考方向 参考原文
------
点击查看相关文件下载
--- ---

一、什么是socket

1. scoket概述

socket是什么?

socket 的原意是插座,插口,但是在计算机通信领域,socket 被翻译为套接字,它是计算机之间进行通信的一种约定或一种方式。它是一个编程接口,是一种特殊的文件描述符 (everything in Unix is a file),它并不仅限于TCP/IP协议,我们可以使用它来进行面向连接 (如Transmission Control Protocol - TCP/IP)的编程,也可以使用它进行面向无连接 (如User Datagram Protocol -UDP Inter-network Packet Exchange - IPX)的编程。

我们通过 socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。为了与远程计算机进行数据传输,还可能需要连接到因特网,而 socket 就是用来连接到因特网的工具。

socket 的典型应用就是 Web 服务器和浏览器:浏览器获取用户输入的 URL,向服务器发起请求,服务器分析接收到的 URL,将对应的网页内容返回给浏览器,浏览器再经过解析和渲染,就将文字、图片、视频等元素呈现给用户。

2. Linux中的socket

UNIX/Linux系统中,为了统一对各种硬件的操作,简化接口,不同的硬件设备也都被看成一个文件。对这些文件的操作,等同于对磁盘上普通文件的操作。为了表示和区分已经打开的文件,UNIX/Linux 会给每个文件分配一个 ID,这个 ID 就是一个整数,被称为文件描述符(File Descriptor),其实这个在前边学习文件IO的时候就了解过这个概念了。

UNIX/Linux 程序在执行任何形式的 I/O 操作时,都是在读取或者写入一个文件描述符。一个文件描述符只是一个和打开的文件相关联的整数,它的背后可能是一个硬盘上的普通文件、FIFO、管道、终端、键盘、显示器,甚至是一个网络连接。需要注意的是网络连接也是一个文件,它也有文件描述符。

Linux内核向应用层提供了socket接口,对于应用程序开发人员来说,我们只需要调用socket接口开发自己的应用程序即可。socket是应用层与TCP/IP协议通信的中间软件抽象层,它是一组接口。在设计模式中,socket其实就相当于一个门面模式,它把复杂的TCP/IP协议隐藏在socket接口后面,对我们来说,一组简单的接口就是全部,让socket去组织数据,以符合指定的协议。

所以,我们无需深入的去理解TCPUDP等各种复杂的TCP/IP协议,前边学习过了,确实超级复杂,但是socket已经为我们封装好了,我们只需要遵循socket的规则去编程,写出的程序自然遵循TCPUDP协议。

Linux中,我们可以通过 socket() 函数来创建一个网络连接实现,或者说打开一个网络文件,socket() 的返回值就是文件描述符。有了文件描述符,我们就可以使用普通的文件操作函数来传输数据了,例如:

  • read() 读取从远程计算机传来的数据;
  • write() 向远程计算机写入数据。

3. Windows中的socket

Windows 也有类似文件描述符的概念,但通常被称为文件句柄。与 UNIX/Linux 不同的是,Windows 会区分 socket 和文件,Windows 就把 socket 当做一个网络连接来对待,因此需要调用专门针对 socket 而设计的数据传输函数,针对普通文件的输入输出函数就无效了。

二、套接字的类型

世界上有很多种套接字(socket),比如 DARPA Internet 地址(Internet 套接字)、本地节点的路径名(Unix套接字)、CCITT X.25地址(X.25 套接字)等。我正在学习的是Internet 套接字,它是最具代表性的,也是最经典最常用的。

根据数据传输的方式,可以将 Internet 套接字分成三种类型:流式套接字数据报套接字原始套接字。通过 socket 创建连接时,我们必须要告诉它使用哪种数据传输方式才行。

1. 流式套接字(SOCK_STREAM)

流格式套接字(Stream Sockets)也叫“面向连接的套接字”,一般在程序中使用 SOCK_STREAM 表示。它提供了一个面向连接、可靠的数据传输服务,数据无差错、无重复的发送且按发送顺序接收。内设置流量控制,避免数据流淹没慢的接收方。数据被看作是字节流,无长度限制。

可以将 SOCK_STREAM 看成一条传送带,只要传送带本身没有问题(不断网),就能保证数据不丢失;同时,较晚传送的数据不会先到达,较早传送的数据不会晚到达,这就保证了数据是按照顺序传递的。

流式套接字可以保证数据高质量的传输,这是因为它使用了 TCP 协议(The Transmission Control Protocol,传输控制协议),前边我们已经了解过了,TCP 协议会控制我们的数据按照顺序到达并且没有错误。

浏览器所使用的 http 协议就基于面向连接的套接字,因为必须要确保数据准确无误,否则加载的 HTML 将无法解析。

2. 数据报套接字(SOCK_DGRAM)

数据报格式套接字(Datagram Sockets)也叫“无连接的套接字”,在程序中使用 SOCK_DGRAM 表示,它提供无连接服务。数据包以独立数据包的形式被发送,不提供无差错保证,数据可能丢失或重复,顺序发送,可能乱序接收,并且数据传输的时候数据包的长度是有限制的吗,一般是32KB

所以使用此种套接字的话,计算机只管传输数据,不作数据校验,如果数据在传输中损坏,或者没有到达另一台计算机,是没有办法补救的。也就是说,数据错了就错了,无法重传。但是恰恰因为数据报套接字所做的校验工作少,所以在传输效率方面比流格式套接字要高。

总的来说,数据报套接字是一种不可靠的、不按顺序传递的、以追求速度为目的的套接字。它使用的是UDPUser Datagram Protocol,用户数据报协议)协议。

一般我们使用的QQ 视频聊天和语音聊天就使用 SOCK_DGRAM 来传输数据

3. 原始套接字(SOCK_RAW)

原始套接字(SOCK_RAW)适用于实现IP数据包通信,可以对较低层次协议如IPICMP直接访问。该套接字一般不会出现在高级网络接口中,它常用于侦听及分析数据包,广泛应用于高级网络编程。使用原始套接字存在络应用程序的兼容性问题,所以一般不推荐使用原始套接字。

三、工作在哪?

image-20220624065401119

socket是用于实现TCPUDP协议的,它就工作在传输层了,但是不能做访问网页这样的事情,因为访问网页所需要的 http 协议位于应用层。