网络编程基础
什么是网络编程
网络编程是指网络上的主机,通过不同的进程,以编程的方式实现网络通信(或称之为网络数据传输)
网络编程中的基本概念
1.发送端和接受端
在一次网络数据传输中:
发送端:数据的发送方进程
接受端:数据的接受方进程
收发端:发送端和接收端两端,也简称为收发端
2.请求和响应
一般来说,获取一个网络资源,涉及到两次网络数据传输
第一次:请求数据的发送 第二次:响应数据的发送
3.客户端和服务端
服务端:在常见的网络数据传输场景下,把提供服务的一方进程,称之为服务端,可以提供对外服务
客户端:获取服务的一方进程,称之为客户端
Socket套接字
概念
Socket套接字,是由系统提供的用于网络通信的技术,是基于TCP/IP协议的网络通信的基本操作单元,基于Socket套接字的网路程序开发就是网络编程
分类
传输层有两个核心协议:TCP/UDP
Socket套接字针对传输层协议分为三类:
1.流套接字(使用TCP协议) 2.数据报套接字(使用UDP协议) 3.原始套接字(用于自定义传输层协议,用于读写内核没有处理的IP协议数据)
这里我们简单了解一下传输层中两个核心协议的主要特点
TCP:有连接,可靠传输,面向字节流,全双工
UDP:无连接,不可靠传输,面向数据报,全双工
有连接/无连接:抽象的概念,虚拟的逻辑上的连接 对于TCP来时,TCP协议中保存了对端的信息
对于UDP来说,UDP协议中不保存双方的信息,就是不连接
可靠传输/不可靠传输:网络上,数据很容易丢失(丢包) 可靠传输,尽可能提高传输成功的概率(如果出现丢包,是能够感知的)
面向字节流/面相数据报:面相字节流:读写数据,以字节为单位 面相数据报:读写数据,是以一个数据报为单位
全双工/半双工: 一个通信链路,支持双向通信(能读,也能写) 一个通信链路,支持单向通信(要么读,要么写)
JAVA数据报套接字通信模型

JAVA流套接字通信模型

Socket编程注意事项

1.客户端和服务端:开发时,经常是基于一个主机开启两个进程作为客户端和服务端,但真是的场景,一般都是不同场景
2.注意目的IP和目的端口号,标识了一次数据传输时要发送数据的终点主机和进程
3.Socket编程我们是使用流套接字和数据报套接字,基于传输层的TCP/UDP协议,但应用层协议也需要考虑,我们在后续会进行学习
UDP数据报套接字编程
DatagramSocket API
DatagramSocket 计算机中的文件是一个广义的概念,还能代指一些硬件设备(操作系统管理硬件的设备,也能抽象成文件,统一进行管理)
网卡->Socket文件,操作网卡的时候,流程和操作普通文件差不多 打开->读写->关闭
操作网卡,直接操作不好操作,把操作网卡转换成Socket文件,Socket文件就相当于"网卡的遥控器"
DatagramSocket构造方法
|--------------------------|--------------------------------------------|
| 方法签名 | 方法说明 |
| DatagramSocket() | 创建一个UDP数据报套接字的Socket,绑定本机任意一个随机端口(一般用于客户端) |
| DatagramSocket(int port) | 创建一个UDP数据报套接字的Socket,绑定本地指定的端口(一般用于服务器) |
端口号:我们用端口号来区分主机上的不同的应用程序
DatagramSocket的方法
|--------------------------------|---------------------------------|
| 方法签名 | 方法说明 |
| void receive(DatagramPacket P) | 从此套接字接受数据报(如果没有接收到数据报,该方法会阻塞等待) |
| void send(DatagramPacket p) | 从此套接字发送数据报包(不会阻塞等待,直接发送) |
| void close() | 关闭此数据报套接字 |
DatagramPacket API
DatagramPacket 表示一个完整的UDP数据报
UDP数据报的载荷数据,就可以通过构造方法来指定
|--------------------------------------------------------------------------|----------------------------------------------------------------------------------------------|
| 方法签名 | 方法说明 |
| DatagramPacket(byte[] buf,int length) | 构造一个DatagramPacket以用来接受数据报,接受的数据保存在字节数组(第一个参数buf)中,接受指定长度(第二个参数length) |
| DatagramPacket(byte[] buf,int offset,int length,SocketAddress address) | 构造一个DatagramSocket来发送数据报的数据报,发送的数据为字节数组(第一个参数buf)中,从0到指定长度(第二个参数length),address指定目的主机的IP和端口号 |
DatagramPacket 方法
|--------------------------|---------------------------------------------|
| 方法签名 | 方法说明 |
| InetAddress getAddress() | 从接收的数据报中,获取发送端主机IP和地址;或从发送的数据报中,获取接收端主句IP地址 |
| int getPort() | 从接收的数据报中,获取发送端的端口号;或从发送的数据报中获取主机端口号 |
| byte[] getData() | 获取数据报中的数据 |
构造UDP发送数据报时,需要传入SocketAddress,该对象可以使用InetSocketAddress 来创建
InetSocketAddress API
构造方法
|----------------------------------------------|-------------------------|
| 方法签名 | 方法说明 |
| InetSocketAddress(InetAddress addr,int port) | 创建一个Socket地址,包含IP地址和端口号 |
TCP流套接字编程
ServerSocket API
ServerSocket 是创建TCP服务器的Socket的API
构造方法
|------------------------|----------------------------|
| 方法签名 | 方法说明 |
| ServerSocket(int port) | 创建一个服务器流套接字Socket,并绑定至指定端口 |
ServerSocket方法
|-----------------|-------------------------------------------------------------------------------|
| 方法签名 | 方法说明 |
| Socket accept() | 开始监听指定端口(创建时绑定的端口),有客户端连接后,有客户端连接后,返回一个服务器Socket对象,并基于该Socket建立与客户端的连接,否则阻塞等待 |
| void close() | 关闭此套接字 |
Socket API
Socket构造方法
|------------------------------|------------------------------------------|
| 方法签名 | 方法说明 |
| Socket(String host,int port) | 创建一个客户端流套接字Socket,并与对应IP的主机上,对应端口的进程建立连接 |
Socket方法
|--------------------------------|-------------|
| 方法签名 | 方法说明 |
| InetAddress getInetAddress() | 返回套接字所连接的地址 |
| InputStream getInputStream() | 返回此套接字的输入流 |
| OutputStream getOutputStream() | 返回该套接字的输出流 |
TCP中的长短连接
TCP发送数据时,需要先建立连接,什么时候关闭连接就决定是短连接还是长连接:
短连接:每次接受到数据并返回响应后,都关闭连接,即是短连接(短连接只能一次收发数据)
长连接:不关闭连接,一直保持连接状态,双方不停的收发数据,即是长连接(长连接可以多次收发数据)
拓展了解:
操作系统内置了IO多路复用,本质上是一个线程同时负责处理多个客户端的请求
BIO(阻塞IO)
JAVA通过NIO(非阻塞IO)来封装IO多路复用