一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第17天,点击查看活动详情。
文章目录
一、网络编程
1.什么是网络编程
网络编程,指网络上的主机,通过不同的进程,以编程的方式实现网络通信(或称为网络数据传输)。
我们只要满足进程不同就行;所以即便是同一个主机,只要是不同进程,基于网络来传输数据,也属于网络编程。
特殊的,对于开发来说,在条件有限的情况下,一般也都是在一个主机中运行多个进程来完成网络编程。
但是,我们一定要明确,我们的目的是提供网络上不同主机,基于网络来传输数据资源:
- 进程A:编程来获取网络资源
- 进程B:编程来提供网络资源
2.网络编程的相关概念
(1)发送端和接收端
在一次网络数据传输时:
- 发送端:数据的发送方进程,称为发送端。发送端主机即网络通信中的源主机。
- 接收端:数据的接收方进程,称为接收端。接收端主机即网络通信中的目的主机。
- 收发端:发送端和接收端两端,也简称为收发端。
注意:发送端和接收端只是相对的,只是一次网络数据传输产生数据流向后的概念。
(2)请求和响应
一般来说,获取一个网络资源,涉及到两次网络数据传输:
- 第一次:请求数据的发送
- 第二次:响应数据的发送。
比如说你到商店买烟,你得先提出你买烟的请求,然后商店才会给你响应,拿烟给你。
(3)客户端和服务端
- 服务端:在常见的网络数据传输场景下,把提供服务的一方进程,称为服务端,可以提供对外服务。
- 客户端:获取服务的一方进程,称为客户端。
对于服务来说,一般是提供:
- 客户端获取服务资源
- 客户端保存资源在服务端
好比在银行办事:
- 银行提供存款服务:用户(客户端)保存资源(现金)在银行(服务端)。
- 银行提供取款服务:用户(客户端)获取服务端资源(银行替用户保管的现金)。
(4)常见的客户端服务端模型
最常见的场景,客户端是指给用户使用的程序,服务端是提供用户服务的程序:
- 客户端先发送请求到服务端
- 服务端根据请求数据,执行相应的业务处理
- 服务端返回响应:发送业务处理结果
- 客户端根据响应数据,展示处理结果(展示获取的资源,或提示保存资源的处理结果)
二、socket套接字
1.概念
Socket套接字,是由系统提供用于网络通信的技术,是基于TCP/IP协议的网络通信的基本操作单元。基于Socket套接字的网络程序开发就是网络编程。
网络编程套接字socket是操作系统给应用程序提供的一组API,称为socket API。 socket的原意是插座。它可以视为应用层与传输层之间的桥梁。我们上篇文章讲过,传输层的核心协议有两种:TCP与UDP。同样的,socket API也有对应的两组:TCP与UDP。
2.socket套接字分类
(1)流套接字:使用传输层TCP协议
TCP,即Transmission Control Protocol(传输控制协议),传输层协议。TCP的特点如下:
- 有连接
- 可靠传输
- 面向字节流
- 全双工
(2)数据报套接字:使用传输层UDP协议
UDP,即User Datagram Protocol(用户数据报协议),传输层协议。UDP的特点如下:
- 无连接
- 不可靠传输
- 面向数据报
- 全双工
下面解释一下上面的特点:
- 有连接与无连接。有连接就像打电话,需要接通了,才能交互数据;无连接就像发微信,不需要接通,就可以传输数据。
- 可靠传输与不可靠传输。可靠传输指的是在传输过程中,发送方知道接收方有没有收到信息,就好比打电话,我们需要确认对方能听到我们的话才开始交流;不可靠传输指的是在传输过程中发送方不知道接收方有没有收到数据,就好比发广播的时候,我们不知道是不是所有人都能听到。这里需要注意的是,可靠传输不是100%能被对方接收到,可靠传输也不就是“安全传输”
- 面向字节流与面向数据报。面向字节流指的是以字节为单位进行传输,类似于文件操作中的字节流。面向数据报指的是以数据报为单位进行传输,一个数据报都会明确大小,一次发送与接收必须是一个完整的数据报,不能是半个,也不能是一个半。
- 全双工。全双工对应的就是半双工。全双工指的是一条链路,双向通信;半双工指的是一条链路单向通信。
3.UDP数据报套接字编程
UDP socket主要涉及两个类:DatagramSocket与DatagramPacket。
Socket是一个DatagramSocket对象,对应到操作系统中的一个socket文件。
【注意】
操作系统中的“文件”是一个广义的概念。我们平时所说的文件,指的是普通文件,也就是硬盘上的数据。实际上,操作系统中的文件还可能表示了一些硬件设备/软件资源。socket文件就对应“网卡”这种硬件设备。
从socket文件读数据,本质上就是在读网卡,而从socket文件写数据,本质上也是在写网卡。
你可以想象socket文件就是一个遥控器,通过遥控器来操作这个网卡。
(1)DatagramSocket API
DatagramSocket 是UDP Socket,用于发送和接收UDP数据报。
DatagramSocket 构造方法:
方法 | 方法说明 |
---|---|
DatagramSocket() | 创建一个UDP数据报套接字的Socket,绑定到本机任意一个随机端口(一般用于客户端) |
DatagramSocket(int port) | 创建一个UDP数据报套接字的Socket,绑定到本机指定的端口(一般用于服务端) |
DatagramSocket 方法:
方法 | 方法说明 |
---|---|
voidreceive(DatagramPacket p) | 从此套接字接收数据报(如果没有接收到数据报,该方法会阻塞等待) |
void send(DatagramPacketp) | 从此套接字发送数据报包(不会阻塞等待,直接发送) |
void close() | 关闭此数据报套接字 |
(2)DatagramPacket API
DatagramPacket是UDP Socket发送和接收的数据报。
DatagramPacket 构造方法:
方法 | 方法说明 |
---|---|
DatagramPacket(byte[] buf, int length) | 构造一个DatagramPacket以用来接收数据报,接收的数据保存在字节数组(第一个参数buf)中,接收指定长度(第二个参数length) |
DatagramPacket(byte[] buf, int offset, int length, SocketAddress address) | 构造一个DatagramPacket以用来发送数据报,发送的数据为字节数组(第一个参数buf)中,从0到指定长度(第二个参数length)。address指定目的主机的IP和端口号。 |
DatagramPacket 方法:
方法 | 方法说明 |
---|---|
InetAddress getAddress() | 从接收的数据报中,获取发送端主机IP地址;或从发送的数据报中,获取接收端主机IP地址 |
int getPort() | 从接收的数据报中,获取发送端主机的端口号;或从发送的数据报中,获取接收端主机端口号 |
byte[] getData() | 获取数据报中的数据 |
构造UDP发送的数据报时,需要传入SocketAddress ,该对象可以使用 InetSocketAddress 来创建。
方法 | 方法说明 |
---|---|
InetSocketAddress(InetAddress addr, int port) | 创建一个Socket地址,包含IP地址和端口号 |
4.TCP流套接字编程
(1)ServerSocket API
ServerSocket 是创建TCP服务端Socket的API。
ServerSocket 构造方法:
方法 | 方法说明 |
---|---|
ServerSocket(int port) | 创建一个服务端流套接字Socket,并绑定到指定端口 |
ServerSocket 方法:
方法 | 方法说明 |
---|---|
Socket accept() | 开始监听指定端口(创建时绑定的端口),有客户端连接后,返回一个服务端Socket对象,并基于该Socket建立与客户端的连接,否则阻塞等待 |
void close() | 关闭此套接字 |
(2)Socket API
Socket 是客户端Socket,或服务端中接收到客户端建立连接(accept方法)的请求后,返回的服务端Socket。
不管是客户端还是服务端Socket,都是双方建立连接以后,保存的对端信息,及用来与对方收发数据的。
Socket 构造方法:
方法 | 方法说明 |
---|---|
Socket(String host, int port) | 开创建一个客户端流套接字Socket,并与对应IP的主机上,对应端口的进程建立连接 |
Socket方法:
方法 | 方法说明 |
---|---|
InetAddress getInetAddress() | 返回套接字所连接的地址 |
InputStream getInputStream() | 返回此套接字的输入流 |
OutputStream getOutputStream() | 返回此套接字的输出流 |
(3)TCP中的长短连接
TCP发送数据时,需要先建立连接,什么时候关闭连接就决定是短连接还是长连接:
- 短连接:每次接收到数据并返回响应后,都关闭连接,即是短连接。也就是说,短连接只能一次收发数据。
- 长连接:不关闭连接,一直保持连接状态,双方不停的收发数据,即是长连接。也就是说,长连接可以
多次收发数据。
对比以上长短连接,两者区别如下:
- 建立连接、关闭连接的耗时:短连接每次请求、响应都需要建立连接,关闭连接;而长连接只需要第一次建立连接,之后的请求、响应都可以直接传输。相对来说建立连接,关闭连接也是要耗时的,长连接效率更高。
- 主动发送请求不同:短连接一般是客户端主动向服务端发送请求;而长连接可以是客户端主动发送请求,也可以是服务端主动发。
- 两者的使用场景有不同:短连接适用于客户端请求频率不高的场景,如浏览网页等。长连接适用于客户端与服务端通信频繁的场景,如聊天室,实时游戏等。
三、预告
下篇文章将介绍的是UDP与TCP两个实例。