套接字基础.
什么是套接字
我们之前已经知道, 应用程序运行在用户空间, 也可以说称之为是用户进程. 而为了网络通信, 我们的应用程序需要经过TCP/IP协议栈的封装和解封装. 这个时候, 应用程序就需要向内核进行申请, 申请什么呢? 就是申请这套接字(socket).
所谓套接字, 其实就是一种IPC的实现机制. IPC的实现机制很多, 什么信号啊, 共享内存啊, 等等. 而socket就是一种实现.主要是允许不同主机(甚至是同一主机)不同进程之间的通信, 从而完成数据交换.
一般我们在这里通常进行的都是System Call, 系统调用, 但是这里我们实际上调用的是Socket库的API, 这个API出现在1983年左右, 早期出现在BSD上后来就被广泛是实现在了Linux上的版本上.
但是我们知道, TCP和UDP的端口是独立的.(都是0-65535)
0号端口是个啥?
这个问题有趣吧, 一般我们可是接触不到这个端口的. 但它依然是一个合法的端口号.
这个端口原本是系统保留的, 但是后来在Unix/Linux网络编程中, 它成为了一个向系统请求下一个可以使用的端口号的端口号.
我们来使用Python来做个实验就知道了:
1
2
3
4
5
6
7
8
9 [root@WWW ~]# python3
Python 3.6.1 (default, Jul 9 2017, 05:20:23)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-11)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>> import socket
>> soc = socket.socket()
>> soc.bind(("127.0.0.1", 0))
>> soc.getsockname()
('127.0.0.1', 51043)
套接字也有很多种类的, 有TCP的套接字, UDP的套接字, 也有什么TCP/UDP都不走的裸套接字. 而这些就分别叫做SOCK_STREAM, SOCK_DGRAM, SOCK_RAW
除了这些分类, 我们还将Socket分为了很多Socket Domain: (Socket域) 这是另外一种分类方式, 主要根据其所使用的地址:
- AF_INET: Address Family: IPv4
- AF_INET6: IPv6
- AF_UNIX: 同一主机上的不同的进程进行通信的时候使用, 效率更佳, 而且不占用协议栈
每一类套接字都提供两种socket, 也就是我们上面说的TCP和UDP的套接字, 即流和数据报
接下来我们扯扯一些套接字相关的系统调用吧:
1 | socket() 创建一个套接字 |