1. Socket简介
Socket通常称为“套接字”,用于描述IP地址和端口,是一个通信链的句柄。应用程序通过套接字向网络发出请求或者应答网络请求。
Socket既不是一个程序,也不是一种协议,而是操作系统提供的用于进程之间通信的一组抽象API。
2. 进程通信相关概念
进程通信的概念最初来源于单机系统。由于每个进程都在自己的地址范围内运行,为了保证两个相互通信的进程之间既互不干扰又能协调一致地工作,操作系统为进程通信提供了相应的设施,如Unix BSD中的管道(pipe)、命名管道(named pipe)和软中断信号(signal)等,但这些都仅限于用在本机进程之间的通信。网间进程通信要解决的是不同主机进程间的相互通信问题。
为此,TCP/IP协议引入了端口、地址和连接的概念。
(1)端口
网络中可以被命名和寻址的通信端口,是操作系统可分配的一种资源。
按照OSI七层网络模型的描述,传输层与网络层在功能上的最大区别是传输层提供进程通信能力。从这个意义上来说,网络通信的最终地址就不仅仅是主机地址了,还包括可以描述进程的某种标识符。为此,TCP/IP协议提出了协议端口(Protocol Port,简称端口)的概念,用于标识通信的进程。
端口是一种抽象的软件结构(包括一些数据结构和I/O缓冲区),类似于文件描述符,每个端口都有一个端口号,用于区别不同的端口。由于TCP/IP传输层的TCP协议和UDP协议是两个完全独立的软件模块,因此各自的端口号也相互独立。如TCP有一个255号端口,UDP也有一个255号端口,二者并不冲突。TCP和UDP中端口的地址都是16bit,即端口号的范围是0~65535。
对于这65536个端口号,有以下规定:
- 端口号小于256的定义为常用端口,服务器一般都是通过常用端口号识别。任何TCP/IP实现所提供的服务都用1~1023之间的端口号,这时用IANA管理的。
- 客户端只需保证该端口号在本机上是唯一的,客户端端口号因存在时间很短暂,又称临时端口号。
- 大多数TCP/IP实现给临时端口号分配1024~5000之间的端口号。大于5000的端口号是为其他服务器预留的。
- 常见的端口有FTP服务的21号端口,HTTP服务的80号端口,SMTP服务的25号端口等。
(2)地址
网络通信中通信的两个进程分别处在不同的机器上。遵循以下原则:
- 某台主机可与多个网络相连,必须指定一个特定的网络地址。
- 网络上每台主机应有一个唯一的地址。
- 每台主机上的每个进程应有在该主机上的唯一标识符。
- 通常,主机地址由网络ID和主机ID组成,在TCP/IP协议中用32位整数值表示;TCP和UDP均使用16位整数的端口号标识用户进程。
(3)连接
两个进程间的通信链路称为连接。连接表现为一些缓冲区和一组协议机制。
3. Socket演示:实现服务器端与客户端的交互
在服务器端使用Socket创建一个服务,端口是8001,这样该服务就可以与多个客户端进行连接和通信了。
这里,我用PHP创建一个socket服务,
在 E:\xampp\htdocs\demo 下新建一个php文件socket_server.php,代码如下:
然后,在cli模式下运行该php文件,命令如下:
php E:\xampp\htdocs\demo\socket_server.php
如此,就开启了一个socket服务器,注意,命令行窗口不可关闭,否则socket服务就停止了。
一旦开启socket服务器,这个服务就会注册到系统的网络服务中,占用8001端口。如果有socket客户端连接该socket服务器端,操作系统就会为客户端自动分配一个随机的临时端口,用来和服务器端8001端口进行通信。
既然此服务已经被注册到操作系统中,实际上它和腾讯QQ服务、FTP服务等是一个级别的,用它能够完成很多事情。为了验证,可以使用Telnet进行连接, 打开命令行,输入:
telnet 127.0.0.1 8001。
由于socket是开放透明的、与编程语言无关的,一旦启用socket服务,任何操作socket的语言都可以访问这个开放的服务。
现在,我们再新建一个socket_client.php文件,用做客户端,代码如下:
(为了测试方便,我的socket服务器和socket客户端在同一个主机上。)
然后,在cli模式下运行
socket_client.php 或者在浏览器中访问它都行,就可以看到客户端与服务器端的交互。