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
被翻译为套接字,它是计算机之间进行通信的一种约定或一种方式。它是一个编程接口,是一种特殊的文件描述符 (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
去组织数据,以符合指定的协议。
所以,我们无需深入的去理解TCP
、UDP
等各种复杂的TCP/IP
协议,前边学习过了,确实超级复杂,但是socket
已经为我们封装好了,我们只需要遵循socket
的规则去编程,写出的程序自然遵循TCP
、UDP
协议。
在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
。
所以使用此种套接字的话,计算机只管传输数据,不作数据校验,如果数据在传输中损坏,或者没有到达另一台计算机,是没有办法补救的。也就是说,数据错了就错了,无法重传。但是恰恰因为数据报套接字所做的校验工作少,所以在传输效率方面比流格式套接字要高。
总的来说,数据报套接字是一种不可靠的、不按顺序传递的、以追求速度为目的的套接字。它使用的是UDP
(User Datagram Protocol
,用户数据报协议)协议。
一般我们使用的QQ
视频聊天和语音聊天就使用 SOCK_DGRAM
来传输数据
3. 原始套接字(SOCK_RAW)
原始套接字(SOCK_RAW
)适用于实现IP
数据包通信,可以对较低层次协议如IP
、ICMP
直接访问。该套接字一般不会出现在高级网络接口中,它常用于侦听及分析数据包,广泛应用于高级网络编程。使用原始套接字存在络应用程序的兼容性问题,所以一般不推荐使用原始套接字。
三、工作在哪?
socket
是用于实现TCP
和UDP
协议的,它就工作在传输层了,但是不能做访问网页这样的事情,因为访问网页所需要的 http
协议位于应用层。