网络编程知识点
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);
System.out.println(inet.getHostAddress());
System.out.println(inet.getHostName());
}
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);
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 {
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();
}
注意:一定要先运行服务器端。要是先运行客户端的话,它会找对应服务器进行建立连接,而服务器还未启动,就会报错。
|