Socket是什么:
socket 的中文解释为“插座”,非常的生动形象。在计算机通信领域,socket 被翻译为“套接字”。它是计算机之间进行通信的一种约定或一种方式。通过 socket ,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。
为什么说Socket解释为插座生动形象:
因为插座起一个对接、连接作用,而Socket在网络连接中基本起到这样一个作用。
通过 socket() 函数来创建一个网络连接,或者说打开一个网络文件,socket() 的返回值就是文件描述符。有了文件描述符,我们就可以使用普通的文件操作函数来传输数据了
例如:
用 read() 读取从远程计算机传来的数据;
用 write() 向远程计算机写入数据。
类似于:Linux,Linux 中的一切都是文件。
为了表示和区分已经打开的文件,UNIX/Linux 会给每个文件分配一个 ID,这个 ID 就是一个整数,被称为文件描述符(File Descriptor)。
例如:
通常用 0 来表示标准输入文件(stdin),它对应的硬件设备就是键盘;通常用 1 来表示标准输出文件(stdout),它对应的硬件设备就是显示器。
Linux 程序在执行任何形式的 I/O 操作时,都是在读取或者写入一个文件描述符。一个文件描述符只是一个和打开的文件相关联的整数,它的背后可能是一个硬盘上的普通文件、FIFO、管道、终端、键盘、显示器,甚至是一个网络连接。
网络连接也是一个文件,它也有文件描述符。只要用 socket() 创建了连接,剩下的就是文件操作了,网络编程原来就是如此简单!
Windows 也有类似“文件描述符”的概念,但通常被称为“文件句柄”。
一个简单的传输架构:
套接字的类型:
在Internet 套接字简单两种:流格式套接字(SOCK_STREAM)、数据报格式套接字(SOCK_DGRAM)。分别基于TCP和UDP。
流格式套接字(SOCK_STREAM):
流格式套接字(Stream Sockets)也叫“面向连接的套接字”,在代码中使用 SOCK_STREAM 表示。
SOCK_STREAM 是一种可靠的、双向的通信数据流,数据可以准确无误地到达另一台计算机,如果损坏或丢失,可以重新发送。SOCK_STREAM 有以下几个特征:
数据在传输过程中不会消失;
数据是按照顺序传输的;
数据的发送和接收不是同步的(有的教程也称“不存在数据边界”)。
可以将 SOCK_STREAM 比喻成一条传送带,只要传送带本身没有问题(不会断网),就能保证数据不丢失;同时,较晚传送的数据不会先到达,较早传送的数据不会晚到达,这就保证了数据是按照顺序传递的。浏览器所使用的 http 协议就基于面向连接的套接字。
数据报格式套接字(SOCK_DGRAM):
数据报格式套接字(Datagram Sockets)也叫“无连接的套接字”,在代码中使用 SOCK_DGRAM 表示。
计算机只管传输数据,不作数据校验,如果数据在传输中损坏,或者没有到达另一台计算机,是没有办法补救的。也就是说,数据错了就错了,无法重传。
因为数据报套接字所做的校验工作少,所以在传输效率方面比流格式套接字要高。
可以将 SOCK_DGRAM 比喻成高速移动的摩托车快递,它有以下特征:强调快速传输而非传输顺序;
传输的数据可能丢失也可能损毁;
限制每次传输的数据大小;
数据的发送和接收是同步的(有的教程也称“存在数据边界”)。
数据报套接字是一种不可靠的、不按顺序传递的、以追求速度为目的的套接字。
QQ 视频聊天和语音聊天就使用 SOCK_DGRAM 来传输数据。
SOCKET的连接建立:
原形为:
int socket(int af, int type, int protocol); af 为地址族(Address Family),也就是 IP 地址类型,常用的有 AF_INET 和 AF_INET6。AF 是“Address Family”的简写,INET是“Inetnet”的简写。AF_INET 表示 IPv4 地址,例如 127.0.0.1;AF_INET6 表示 IPv6 地址,例如 1030::C9B4:FF12:48AA:1A2B。 需要记住127.0.0.1,它是一个特殊IP地址,表示本机地址。 也可以使用 PF 前缀,PF 是“Protocol Family”的简写,它和 AF 是一样的。例如,PF_INET 等价AF_INET,PF_INET6 等价于 AF_INET6。 type 为数据传输方式/套接字类型,常用的有 SOCK_STREAM(流格式套接字/面向连接的套接字) 和SOCK_DGRAM(数据报套接字/无连接的套接字),我们已经在《套接字有哪些类型》一节中进行了介绍。 protocol 表示传输协议,常用的有 IPPROTO_TCP 和 IPPTOTO_UDP,分别表示 TCP 传输协议和 UDP 传输协议。
TCP下:
int tcp_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //IPPROTO_TCP表示TCP协议
UDP下:
int udp_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); //IPPROTO_UDP表示UDP协议
上面两种情况都只有一种协议满足条件,可以将 protocol 的值设为 0,系统会自动推演出应该使用什么协议:
int tcp_socket = socket(AF_INET, SOCK_STREAM, 0); //创建TCP套接字 int udp_socket = socket(AF_INET, SOCK_DGRAM, 0); //创建UDP套接字
要想知道完整的TCP的socket连接可查看我另一篇博客:
嵌入式编写TCP连接过程