网络编程知识点
1. 网络编程概述
-
计算机网络:
把分布在不同地理区域的具有独立功能的计算机,通过通信设备(路由器或交换机之类的)与线路连接起来,由功能完善的软件实现资源共享和信息传递的系统。
-
Java是Internet上的语言,它从语言级上提供了对网络应用程序的支持,程序员能够很容易开发常见的网络应用程序。
-
Java提供的网络类库,可以实现网络连接,联网的底层细节被隐藏在Java的本机安装系统里,由**
JVM
**进行控制。并且Java实现了一个跨平台的网络库,程序员面对的是一个统一的网络编程环境。 -
网络编程的目的:
直接或间接地通过网络协议与其他计算机进行通讯。
-
网络编程中有两个主要的问题:
如何准确地定位网络上一台或者多台主机
IP
地址 找到主机后如何可靠高效地进行数据传输 通信协议
2.网络通信模型及协议
OSI
七层模型(理想型):物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。
TCP/IP
参考模型(我们实际中使用应用到的):物理层(物理+数据链路层)、网络层、传输层、应用层。
应用层:指我们编程语言级别的,所封装的一些数据。
传输层:就是用那些协议进行传输。
网络层:进行定位,如何定位到一台主机。
物理层:一些物理设备,网线、线路进行最底层的数据传输。
协议:
网络层:HTTP(最常用的)、ftp
(连接一些网络服务,向服务器端进行文件传输)等
传输层:TCP(提出三次握手,四次挥手)、UDP
等
网络层:IP
等
如何实现网罗中的主机互相通信:
通信双方地址
一定的规则
3.通讯要素:IP
和端口号
IP
地址:InetAddress
唯一的标识 Internet 上的计算机
本地回环地址(hostAddress
):127.0.0.1 主机名(hostName
):localhost
IP
地址分类方式1:IPV4
和IPV6
`IPV4`:4个字节组成,4个0-255。以点分十进制表示,如192.168.31.24
IPV6
:128位(16个字节),写成8个无符号整数,每个整数用四个十六进制位表示,数之间用冒号(:)分开,如:3ffe:3201:1401:1280:c8ff:fe4d:db39:1984
IP
地址分类方式2:公网地址(万维网使用)和私有地址(局域网使用),192.168. 开头的就是私有地址,范围即为192.168.0.0-192.168.255.255,专门为机构组织内部使用
特点:不易记忆 ,解决方法:申请域名进行绑定。DNS
服务器,管理全球域名,不会重复。
端口号标识正在计算机上运行的进程(程序)
不同的进程有不同的端口号
被规定为一个16位的整数 0~65534。
端口分类:
**公认端口:**0-1023,被预先定义的服务通信占用(如:HTTP占用端口80,FTP占用端口21,TeInet
占用端口23)
**注册端口:**1024-49151,分配给用户进程或应用程序。(如:Tomcat占用端口8080,MySQL
占用端口3306,Oracle占用端口1521等)。
**动态/私有端口:**49152-65535,运行过程中自动分配
端口号与IP
地址的组合得出一个网络套接字。
4.InetAddress
类
InetAddress
类
Internet上的主机有两种方式表示地址:
域名(hostName
):www.baidu.com
**IP
地址(hostAddress
):**36.152.44.95
InetAddress
类主要表示IP
地址,两个子类:Inet4Address
、Inet6Address
InetAddress
类对象含有一个Internet主机地址的域名和IP
地址,如www.baidu.com 和 36.152.44.95
域名容易记忆,当在连接网络时输入一个主机的域名后,域名服务器(DNS
)负责将域名转化为IP
地址,这样才能和主机建立连接。(域名解析)
public static void main(String[] args) throws UnknownHostException {
InetAddress inet = InetAddress.getByName("www.baidu.com");
System.out.println(inet); // www.baidu.com/36.152.44.95
System.out.println(inet.getHostAddress()); // 主机地址 36.152.44.95
System.out.println(inet.getHostName()); // 主机名 www.baidu.com
}
5.通信要素:网络通信协议
网络通信协议:
计算机网络中实现通信必须有一些约定,即通信协议,对速率、传输代码、代码结构、传输控制步骤、出错控制等制定标准。
通信协议分层的思想:
由于结点之间联系很复杂,在制定协议时,把复杂成份分解成一些简单的成份,再将它们复合起来。最常用的复合方式是层次方式,即同层间可以通信、上一层可以调用下一层,而与再下一层不发生关系。各层互不影响,利于系统的开发和扩展。
协议:
网络层:
HTTP协议(超文本传输协议):超文本,指网页内容。就是传输网页内容的一个协议。
FTP协议:传输的是文件。
传输层:
传输控制协议TCP
(Transmission Control Protocol)
用户数据报协议UDP
(User Datagram Protocol)
网络层:
IP
协议(网络互联协议):支持网络间互联的数据通信。
TCP/IP
以其两个主要协议:传输控制协议(TCP)和网络互联协议(IP
)而得名,实际上是一组协议,包括多个具有不同功能且互为关联的协议。
6.传输控制协议TCP
TCP
使用TCP协议前,需先建立TCP连接,形成传输数据通道(传输数据之前,客户端与服务器必须建立连接)。
传输前,采用“三次握手”方式,是可靠的。
TCP协议进行通信的两个应用进程:客户端、服务器端
在连接中可进行大数据量的传输
传输完毕,需释放已建立的连接,效率低
在断开时要进行“四次挥手”
三次握手
标志位(Flags):共6个,即URG
、ACK
、PSH
、RST
、SYN
、FIN
等。具体含义如下:
URG
:紧急指针(urgent pointer) 有效。
ACK
:确认序号有效。
PSH
:接收方应该尽快将这个报文交给应用层。
RST
:重置连接。
SYN
:发起一个新连接。
FIN
:释放一个连接。
seq是一个序列化编号。
使用TCP协议前,需先建立TCP连接,传输前,采用“三次握手”方式:
1.客户端向服务器端发起连接请求
2.服务器端收到请求后向客户端的确认回复
3.客户端收到服务器端的确认回复后再给服务器端的确认回复,这样服务器端就能确保客户端收到了来自服务器的确认回复。
面试问:两次握手行不行?四次行不行?
两次太少,四次太多
四次挥手
在断开时要进行“四次挥手”,服务器端与客户端都可以主动要求断开连接,这里以客户端主动断开连接为例:
- 客户端向服务器端发送一个断开连接的请求(FIN)。
- 服务器端收到后向客户端发送一个确认信息,还可以发送数据。
- 之后,服务器端又向客户端发送一个断开连接的请求(FIN)。
- 客户端向服务器端发送确认断开的一个回复。
7.用户数据报协议UDP
UDP
将数据、数据源、目的地址封装成数据包(报),不需要建立连接。
每个数据包的大小限制在64K
内。
因无需连接,故是不可靠的。
发送数据结束时无需释放资源,速度快
8. Java中TCP协议通信实现
Socket
Socket:网络套接字,表示客户端,里面封装服务器IP
,端口
利用套接字(Socket)开发网络应用程序早已被广泛的采用,以至于称为事实上的标准。
通信的两端都要有Socket,是两台机器间通信的端点。
网络通信其实就是Socket间的通信。
Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输。
一般主动发起通信的应用程序属客户端,等待通信请求的为服务端。
Java语言基于套接字编程分为服务端编程和客户端编程,其通信模型如图所示:
客户端Socket的工作过程包含以下四个基本的步骤:
**创建Socket:**根据指定服务器的IP
地址或端口号构造Socket类对象。若服务器端响应,则建立客户端到服务器的通信线路。弱连接失败,会出现异常。
**打开连接到Socket的输入/输出流:**使用getInputStream()
方法获得输入流,使用getOutputStream()
方法获得输出流,进行数据传输。
**按照一定的协议对Socket进行读/写操作:**通过输入流读取服务器放入线路的信息(但不能读取自己放入线路的信息),通过输出流将信息写入线程。
**关闭Socket:**断开客户端到服务器的连接,释放线路。
客户端程序可以使用Socket类创建对象,创建的同时会自动向服务器方发起连接。Socket的构造方法是:
Socket(String host,int port):向服务器(域名是host。端口号为port)发起TCP连接,若成功,则创建Socket对象,否则抛出异常。
Socket(InetAddress address,int port)
:根据InetAddress
对象所表示的IP
地址以及端口号port发起连接。
服务器端程序的工作过程包含以下四个基本的步骤:
调用ServerSocket
:表示服务器端。创建一个服务器端套接字,并绑定到指定端口上。用于监听客户端的请求/连接。
**调用accept():**监听连接请求,如果客户端请求连接,则接受连接,返回通信套接字对象。
**调用该Socket类对象的getOutputStream()
和getInputStream()
:**获取输出流和输入流,开始网络数据的发送和接收。
**关闭ServerSocket
和Socket对象:**客户端访问结束,关闭通信套接字。
服务器建立ServerSocket
对象,ServerSocket
对象负责等待客户端请求建立套接字连接,即:服务器必须事先建立一个等待客户端请求建立套接字连接的ServerSocket
对象。所谓“接收”客户端的套接字请求,就是accept()方法会返回一个Socket对象。
一个案例
服务器端
//服务器
public class Server {
public static void main(String[] args) throws IOException {
//创建服务器,端口号自定义 不要跟其他的重复
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务器启动,等待客户端连接");
//服务器监听等待客户端请求连接
Socket socket = serverSocket.accept();//阻塞式的 监听
System.out.println("客户端连接成功");
//接收客户单发送的消息
InputStream in = socket.getInputStream();
byte[] b=new byte[1024];
int length = in.read(b);//将客户端发送的消息 写入到byte数组中
//byte数组转字符串
String s = new String(b,0,length,"utf-8");
System.out.println("接收到客户端消息:"+s);
//服务器端向客户单发送消息
OutputStream out = socket.getOutputStream();
out.write("我收到了".getBytes("utf-8"));
}
}
客户端
//客户端
public class Client {
public static void main(String[] args) throws IOException {
//创建客户端 创建时需要进行建立连接
//IP为电脑IP,端口为服务器端自定义的端口
Socket socket = new Socket("192.168.31.132",9999);
//获得输出流对象
OutputStream out = socket.getOutputStream();
String s = "你好 服务器";
out.write(s.getBytes("utf-8"));
//客户端接收服务器发送的消息
InputStream in = socket.getInputStream();
byte[] b=new byte[1024];
int length = in.read(b);
String ms = new String(b, 0, length, "utf-8");
System.out.println("接收到服务器消息"+ms);
out.close();
socket.close();
}
注意:一定要先运行服务器端。要是先运行客户端的话,它会找对应服务器进行建立连接,而服务器还未启动,就会报错。