在Linux中,一切多是文件,除了文本文件、源文件、二进制文件等,一个硬件装备也可以被映射为一个虚拟的文件,称为装备文件。例如,stdin 称为规范输出文件,它对应的硬件装备普通是键盘,stdout 称为规范输入文件,它对应的硬件装备普通是显示器。关于一切的文件,都可以运用 read() 函数读取数据,运用 write() 函数写入数据。
“一切多是文件”的思惟极大地简化了程序员的了解和操作,使得对硬件装备的处置就像通俗文件一样。一切在Linux中创立的文件都有一个 int 类型的编号,称为文件描绘符(File Descriptor)。运用文件时,只需晓得文件描绘符就可以。例如,stdin 的描绘符为 0,stdout 的描绘符为 1。
在Linux中,socket 也被以为是文件的一种,和通俗文件的操作没有差别,所以在收集数据传输进程中天然可以运用与文件 I/O 相干的函数。可以以为,两台盘算机之间的通讯,实践上是两个 socket 文件的互相读写。
文件描绘符有时也被称为文件句柄(File Handle),但“句柄”次要是 Windows 中术语,所以本教程中假如触及到 Windows 平台将运用“句柄”,假如触及到 Linux 平台将运用“描绘符”。

在Linux下创立 socket

在 Linux 下运用 <sys/socket.h> 头文件中 socket() 函数来创立套接字,原型为:

int socket(int af, int type, int protocol);

1) 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。

2) type 为数据传输方法,常用的有 SOCK_STREAM 和 SOCK_DGRAM,在《socket是什么意思》一节中曾经停止了引见。
3) protocol 表现传输协定,常用的有 IPPROTO_TCP 和 IPPTOTO_UDP,辨别表现 TCP 传输协定和 UDP 传输协定。
有了地址类型和数据传输方法,还缺乏以决议采取哪一种协定吗?为什么还需求第三个参数呢?
正如人人所想,普通状况下有了 af 和 type 两个参数就可以创立套接字了,操作零碎会主动推上演协定类型,除非碰到如许的状况:有两种分歧的协定支撑统一种地址类型和数据传输类型。假如我们不指明运用哪一种协定,操作零碎是没方法主动推演的。
该教程运用 IPv4 地址,参数 af 的值为 PF_INET。假如运用 SOCK_STREAM 传输数据,那么知足这两个前提的协定只要 TCP,因而可以如许来挪用 socket() 函数:

int tcp_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);  //IPPROTO_TCP表现TCP协定

这种套接字称为 TCP 套接字。
假如运用 SOCK_DGRAM 传输方法,那么知足这两个前提的协定只要 UDP,因而可以如许来挪用 socket() 函数:

int udp_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);  //IPPROTO_UDP表现UDP协定

这种套接字称为 UDP 套接字。
下面两种状况都只要一种协定知足前提,可以将 protocol 的值设为 0,零碎会主动推上演应当运用什么协定,如下所示:

int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);  //创立TCP套接字
int udp_socket = socket(AF_INET, SOCK_DGRAM, 0);  //创立UDP套接字

前面的教程中多采取这种简化写法。

在Windows下创立socket

Windows 下也运用 socket() 函数来创立套接字,原型为:

SOCKET socket(int af, int type, int protocol);

除了前往值类型分歧,其他多是相反的。Windows 不把套接字作为通俗文件看待,而是前往 SOCKET 类型的句柄。请看下面的例子:

SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);  //创立TCP套接字