JavaSE基础十---<网络编程>网络编程概述||通讯要素:IP和端口号,网络通信协议||关于InetAddress类||实现TCP通信||实现UDP通信
Posted 小智RE0
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaSE基础十---<网络编程>网络编程概述||通讯要素:IP和端口号,网络通信协议||关于InetAddress类||实现TCP通信||实现UDP通信相关的知识,希望对你有一定的参考价值。
目录
1.网络编程概述
计算机网络:把分布在不同地理区域的具有独立功能的计算机,通过通信设备与线路(网线)连接起来,由功能完善的软件实现资源共享和信息传递的系统。
• Java是 Internet 上的语言,它从语言级上提供了对网络应用程序的支持,可开发常见的网络应用程序。
• Java提供的网络类库,可以实现网络连接,联网的底层细节被隐藏在 Java 的本机安装系统中,由 JVM 进行控制。并且 Java 实现的跨平台的网络库,程序员面对的是一个统一的网络编程环境。
• 网络编程的目的:
直接或间接地通过网络协议与其它计算机进行通讯。
• 网络编程中有两个主要的问题:
(1)通过IP地址,准确地定位网络上一台或多台主机
(2)找到主机后,通过通信协议可靠高效地进行数据传输。
网络通信协议
- 物理层和数据链路层涉及物理介质访问和二进制数据流传输。
- 网络层的主要涉及寻址和路由选择.
- 传输层的基本功能是为两台主机间的应用程序提供端到端的通信。传输层从应用层接受数据,并且在必要的时候把它分成较小的单元,传递给网络层,并确保到达对方的各段信息正确无误.
- 应用层提供应用程序的网络接口.
数据的简化传输过程
2.通讯要素:IP和端口号||关于InetAddress类
IP地址
IP 地址:InetAddress(Internet Protocol Address)是指互联网协议地址,又译为网际协议地址。IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。)
- Internet 上的计算机唯一的标识
- 本地回环地址(hostAddress):127.0.0.1
- 主机名(hostName):localhost
IP地址分类方式1:IPV4和IPV6
IPV4:4个字节组成,4个0-255的数的组合,大概42亿,30亿都在北美,亚洲4亿,2011年初已经用尽。以点分十进制表示,如192.168.0.1
(点分十进制(Dotted Decimal Notation)全称为点分(点式)十进制表示法,是IPv4的IP地址标识方法。IPv4中用四个字节表示一个IP地址,每个字节按照十进制表示为0255。点分十进制就是用4个从0255的数字,来表示一个IP地址。如192.168.1.1)
IPV6:128位(16个字节),写成8个无符号整数,每个整数用四个十六进制位表示,数之间用冒号(:)分开,如:3ffe:3201:1401:1280:c8ff.fe4d:db39:1984
IP地址分类方式2:公网地址(万维网使用)和私有地址(局域网使用)
公网IP是在Internet使用的IP地址,而私有IP地址则是在局域网中使用的IP地址。
以192.168.开头的就是私有地址,范围是192.168.0.0-192.168.255.255,专门为组织机构内部使用.
由于IP地址不方便记忆,则出现DNS域名服务器来管理全球域名.
DNS(Domain Name Server,域名服务器)是进行域名(domain name)和与之相对应的IP地址 (IP address)转换的服务器。DNS中保存了一张域名(domain name)和与之相对应的IP地址 (IP address)的表,以解析消息的域名。 域名是Internet上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置)。域名是由一串用点分隔的名字组成的,通常包含组织名,而且始终包括两到三个字母的后缀,以指明组织的类型或该域所在的国家或地区。
域名系统(英文:Domain Name System,缩写:DNS)是互联网的一项服务。它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。DNS使用UDP端口53。当前,对于每一级域名长度的限制是63个字符,域名总长度则不能超过253个字符。
端口号
端口号:标识正在计算机上运行的进程(程序)
[所谓的端口,就好像是门牌号一样,客户端可以通过ip地址找到对应的服务器端,但是服务器端是有很多端口的,每个应用程序对应一个端口号,通过类似门牌号的端口号,客户端才能真正的访问到该服务器。为了对端口进行区分,将每个端口进行了编号,这就是端口号]
- 不同的进程有不同的端口号.
- 被规定为一个 16 位的整数 0~65535。
端口分类:
公认端口:0-1023,被预先定义的服务通信占用(如:HTTP占用端口80,FTP占用端口21,Telnet占用端口23)
注册端口:1024-49151,分配给用户进程或应用程序。(如:Tomcat占用端口8080,mysql占用端口3306,Oracle占用端口1521等)。
动态/私有端口:49152-65535.
端口号与IP地址的组合得出一个网络套接字。
所谓套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议根进行交互的接口.
套接字Socket=(IP地址:端口号),套接字的表示方法是点分十进制的lP地址后面写上端口号,中间用冒号或逗号隔开。每一个传输层连接唯一地被通信两端的两个端点(即两个套接字)所确定。例如:如果IP地址是210.37.145.1,而端口号是23,那么得到套接字就是(210.37.145.1:23)
InetAddress类
此类表示互联网协议 (IP) 地址。
Internet上的主机有两种方式表示地址:
例如:
域名(hostName):www.baidu.com
IP 地址(hostAddress):220.181.111.37
- InetAddress类主要表示IP地址,两个子类:Inet4Address、Inet6Address。
- InetAddress 类对象含有一个 Internet 主机地址的域名和IP地址:www.baidu.com和 220.181.111.37
- 相对于IP地址,域名容易记忆,当在连接网络时输入一个主机的域名后,域名服务器(DNS)负责将域名转化成IP地址,这样才能和主机建立连接。即为域名解析.
常用方法
返回值类型 | 方法 | 注释 |
---|---|---|
boolean | equals(Object obj) | 将此对象与指定对象比较 |
byte[ ] | getAddress( ) | 返回此 InetAddress 对象的原始 IP 地址 |
static InetAddress[ ] | getAllByName(String host) | 在给定主机名的情况下,根据系统上配置的名称服务返回其 IP 地址所组成的数组 |
static InetAddress | getByAddress(byte[] addr) | 在给定原始 IP 地址的情况下,返回 InetAddress 对象 |
static InetAddress | getByAddress(String host, byte[] addr) | 根据提供的主机名和 IP 地址创建 InetAddress |
static InetAddress | getByName(String host) | 在给定主机名的情况下确定主机的 IP 地址 |
String | getCanonicalHostName ( ) | 获取此 IP 地址的完全限定域名 |
String | getHostAddress( ) | 返回 IP 地址字符串(以文本表现形式) |
String | getHostName( ) | 获取此 IP 地址的域名 |
static InetAddress | getLocalHost( ) | 返回本地主机 |
String | toString( ) | 将此 IP 地址转换为 String |
例如:
public class Demo01 {
public static void main(String[] args) throws UnknownHostException {
InetAddress i1=InetAddress.getByName("www.baidu.com");
System.out.println(i1);//在给定主机名的情况下确定主机的 IP 地址
System.out.println(i1.getHostAddress());//返回 IP 地址字符串
System.out.println(i1.getHostName());//获取此 IP 地址的域名
}
}
3.通讯要素:网络通信协议
网络协议:指的是计算机网络中互相通信的对等实体之间交换信息时所必须遵守的规则的集合.(计算机网络中实现通信的一些约定对速率、传输代码、代码结构、 传输控制步骤、出错控制等制定标准)
例如,网络中一个微机用户和一个大型主机的操作员进行通信,由于这两个数据终端所用字符集不同,因此操作员所输入的命令彼此不认识。为了能进行通信,规定每个终端都要将各自字符集中的字符先变换为标准字符集的字符后,才进入网络传送,到达目的终端之后,再变换为该终端字符集的字符。当然,对于不相容终端,除了需变换字符集字符外还需转换其他特性,如显示格式、行长、行数、屏幕滚动方式等也需作相应的变换。
通信协议分层的思想
由于结点之间联系很复杂,在制定协议时,把复杂成分分解成一些简单的成份,再将它们复合起来。
最常用的复合方式是层次方式,即同层间可以通信、上一层可以调用下一层,而与再下一层不发生关系。各层互不影响,利于系统的开发和扩展。
由于网络节点之间联系的复杂性,在制定协议时,通常把复杂成分分解成一些简单成分,然后再将它们复合起来。最常用的复合技术就是层次方式,网络协议的层次结构如下:
(1)结构中的每一层都规定有明确的服务及接口标准。
(2)把用户的应用程序作为最高层
(3)除了最高层外,中间的每一层都向上一层提供服务,同时又是下一层的用户。
(4)把物理通信线路作为最低层,它使用从最高层传送来的参数,是提供服务的基础。
传输层协议中有两个非常重要的协议:
- 传输控制协议TCP(Transmission Control Protocol)
- 用户数据报协议UDP(User Datagram Protocol)
(3.1)TCP传输控制协议的概念
传输控制协议(TCP):TCP(传输控制协议)定义了两台计算机之间进行可靠的传输而交换的数据和确认信息的格式,以及计算机为了确保数据的正确到达而采取的措施。协议规定了TCP软件怎样识别给定计算机上的多个目的进程如何对分组重复这类差错进行恢复。协议还规定了两台计算机如何初始化一个TCP数据流传输以及如何结束这一传输。TCP最大的特点就是提供的是面向连接、可靠的字节流服务。
TCP/IP 以它的两个主要协议:传输控制协议(TCP)和网络互联协议(IP)而得名,实际上是一组协议,包括多个具有不同功能且互为关联的协议。
IP(Internet Protocol)协议是网络层的主要协议,支持网间互连的数据通信。
IP是Internet Protocol(网际互连协议)的缩写,是TCP/IP体系中的网际层协议。设计IP的目的是提高网络的可扩展性:一是解决互联网问题,实现大规模、异构网络的互联互通;二是分割顶层网络应用和底层网络技术之间的耦合关系,以利于两者的独立发展。根据端到端的设计原则,IP只为主机提供一种无连接、不可靠的、尽力而为的数据包传输服务。
IP是整个TCP/IP协议族的核心,也是构成互联网的基础。IP位于TCP/IP模型的网络层(相当于OSI模型的网络层),它可以向传输层提供各种协议的信息,例如TCP、UDP等;对下可将IP信息包放到链路层,通过以太网、令牌环网络等各种技术来传送。
为了能适应异构网络,IP强调适应性、简洁性和可操作性,并在可靠性做了一定的牺牲。IP不保证分组的交付时限和可靠性,所传送分组有可能出现丢失、重复、延迟或乱序等问题。
(1)使用TCP协议前,须先建立TCP连接,形成传输数据通道.
(2)传输前,采用“三次握手”方式,保证数据是安全可靠的.
关于三次握手的简图:
(3)TCP协议进行通信的两个应用进程为:客户端、服务端.
(4)在连接中可进行大数据量的传输.
(5)传输完毕,需释放已建立的连接,所以效率低.
(6)最后在断开时要进行“四次挥手”.
关于四次挥手简图:
实际中的三次握手:
标志位(Flags):共6个,即URG、ACK、PSH、RST、SYN、FIN等,具体含义如下:
URG:紧急指针(urgent pointer)有效。
ACK:确认序号有效。
PSH:接收方应该尽快将这个报文交给应用层。
RST:重置连接。
SYN:发起一个新连接。
FIN:释放一个连接。
四次挥手:
TCP通信特点:
在传输之前,客户端与服务器之间必须建立连接;传输数据是安全可靠的,可以进行大量数据的传输;但是在结束时需要断开连接;效率低
(3.2)UDP用户数据报协议的概念
用户数据报协议(UDP):UDP(用户数据报协议)是一个简单的面向数据报的传输层协议。提供的是非面向连接的、不可靠的数据流传输。UDP不提供可靠性,也不提供报文到达确认、排序以及流量控制等功能。它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。因此报文可能会丢失、重复以及乱序等。但由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。
(1)将数据、源、目标地址封装成数据包,不需要建立连接,直接发送数据.
(2)每个数据报的大小限制在64K内.
(3)由于无需连接,所以是不可靠的.
(4)发送数据结束时无需释放资源,传输速度快.
(3.3)TCP通信的Java实现
- 利用套接字(Socket)开发网络应用程序早已被广泛的采用,以至于成为事实上的标准。
- 通信的两端都要有Socket,是两台机器间通信的端点
- 网络通信其实就是Socket间的通信。
- Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输。
Socket—网络套接字,表示客户端,里面封装了服务器IP以及端口.
套接字是通信的基石,是支持TCP/IP协议的路通信的基本操作单元。可以将套接字看作不同主机间的进程进行双间通信的端点,它构成了单个主机内及整个网络间的编程界面。套接字存在于通信域中,通信域是为了处理一般的线程通过套接字通信而引进的一种抽象概念。套接字通常和同一个域中的套接字交换数据(数据交换也可能穿越域的界限,但这时一定要执行某种解释程序),各种进程使用这个相同的域互相之间用Internet协议簇来进行通信
ServerSocket—表示服务器端,监听客户端的连接.
一般主动发起通信的应用程序属客户端,等待通信请求的为服务端
客户端程序可以使用Socket类创建对象,创建的同时会自动向服务器方发起连接
Socket的构造方法:
- Socket(String host,int port)throws UnknownHostException,IOException:向服务器(域名是host。端口号为port)发起TCP连接,若成功,则创建Socket对象,否则抛出异常。
- Socket(InetAddress address,int port)throws IOException:根据InetAddress对象所表示的IP地址以及端口号port发起连接。
Socket常用方法
方法 | 注释 |
---|---|
void close( ) throws IOException | 关闭Socket,不可在以后的网络连接中使用,除非创建新的套接字 |
InputStream getInputStream()throws IOException | 获取与Socket相关联的字节输入流,用于从Socket中读数据 |
OutputStream getOutputStream()throws IOException | 获取与Socket相关联的字节输出流,用于向Socket中写数据 |
服务器建立 ServerSocket 对象
ServerSocket 对象负责等待客户端请求建立套接字连接,类似邮局某个窗口中的业务员。也就是说,服务器必须事先建立一个等待客户请求建立套接字连接的ServerSocket对象。
所谓“接收”客户的套接字请求,就是accept( )方法会返回一个 Socket 对象.
ServerSocket常用方法
方法 | 注释 |
---|---|
Socket accept( ) throws IOException | 等待客户端的连接请求,返回与该客户端进行通信用的Socket对象 |
void close( )throws IOException | 关闭监听Socket |
客户端和服务器之间的传输
客户端Socket的工作过程包含以下四个基本的步骤:
- 创建 Socket:根据指定服务端的 IP 地址或端口号构造 Socket 类对象。若服务器端响应,则建立客户端到服务器的通信线路。若连接失败,会出现异常。
- 打开连接到 Socket 的输入/出流: 使用 getInputStream( )方法获得输入流,使用 getOutputStream( )方法获得输出流,进行数据传输
- 按照一定的协议对 Socket 进行读/写操作:通过输入流读取服务器放入线路的信息(但不能读取自己放入线路的信息),通过输出流将信息写入线程。
- 关闭 Socket:断开客户端到服务器的连接,释放线路 .
服务器程序的工作过程包含以下四个基本的步骤:
- 调用 ServerSocket(int port) :创建一个服务器端套接字,并绑定到指定端口上。用于监听客户端的请求。
- 调用 accept():监听连接请求,如果客户端请求连接,则接受连接,返回通信套接字对象。
- 调用 该Socket类对象的 getOutputStream() 和 getInputStream ():获取输出流和输入流,开始网络数据的发送和接收。
- 关闭ServerSocket和Socket对象:客户端访问结束,关闭通信套接字。
基本代码实现
服务器Server:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
//模拟服务器端
public class Server {
public static void main(String[] args) throws IOException {
//创建服务器
ServerSocket ss=new ServerSocket(5277);
System.out.println("服务器启动,等待客户端的连接.");
//服务器监听,等待客户端请求连接;
//阻塞式的监听;
Socket sks= ss.accept();
System.out.println("客户端已经连接成功");
//服务器接收客户端的消息
InputStream is=sks.getInputStream();
byte[] bytes=new byte[1024];
//获取实际读取的内容长度;
int length=is.read(bytes);
//byte数组转为字符串;
String s=new String(bytes,0,length,"utf-8");
//服务器接收到的消息;
System.out.println("服务器收到的来自客户端"+s);
//服务器端向客户端发送消息
OutputStream os= sks.getOutputStream();
os.write("服务器表示:我收到了".getBytes("utf-8"));
//关闭服务器
ss.close();
}
}
客户端Client:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
//模拟客户端
public class Client {
public static void main(String[] args) throws IOException {
//创建客户端,输入主机名和端口;创建连接;
Socket sk=new Socket("127.0.0.1",5277);
//创建输出流对象
OutputStream os=sk.getOutputStream();
String s="客户端表示:发给服务器";
os.write(s.getBytes("utf-8"));
//客户端接收服务器消息
InputStream is = sk.getInputStream();
byte[] b=new byte[1024];
int length = is.read(b);
String s2 = new String(b, 0, length, "utf-8");
System.out.println("客户端接收到服务器的"+s2);
//关闭流
os.close();
//关闭客户端
sk.close();
}
}
先执行服务器,然后执行客户端
最终:
服务器:
客户端:
(3.4)UDP通信的Java实现
DatagramSocket 和 DatagramPacket 实现了基于 UDP 协议网络程序。
-
DatagramSocket:表示用于发送和接收数据报数据包的套接字。 数据包套接字是分组传送服务的发送或接收点。
-
UDP数据报通过数据报套接字 DatagramSocket 发送和接收,系统不保证UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达。
-
DatagramPacket :表示数据报包。 数据报包用于实现无连接分组传送服务。
-
DatagramPacket 对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号。
-
UDP协议中每个数据报都给出了完整的地址信息,因此无须建立发送方和接收方的连接
DatagramSocket类的发送与接收方法
返回值 | 方法 |
---|---|
void | send(DatagramPacket p) 从此套接字发送数据报包。 |
void receive(DatagramPacket p) | 从此套接字接收数据报包。 |
流程:
- 建立发送端,接收端
- 建立数据包
- 调用Socket的发送、接收方法
- 关闭Socket
模拟发送端Client:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
//模拟发送端
public class Client {
public static void main(String[] args) throws IOException {
//发送端DatagramSocket ;仅发送数据;不会去确定是否可收到;
DatagramSocket datagramSocket = new DatagramSocket();
//封装数据报
byte [] b = "发送端说:接收端你好".getBytes("utf-8");
//这里使用InetAddress类,在给定主机名的情况下确定主机的 IP 地址;
InetAddress inetAddress = InetAddress.getByName("127.0.0.1");
//新建数据报对象;这里传入数据包,以及IP地址和端口名;
DatagramPacket datagramPacket = new DatagramPacket(b,0,b.length,inetAddress,5277);
//发送数据包
datagramSocket.send(datagramPacket);
}
}
模拟接收端Server:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
//模拟接收端
public class Server {
public static void main(String[] args) throws IOException {
//新建接收端DatagramSocket,
DatagramSocket datagramSocket = new DatagramSocket(5277);
//封装数据包
byte[] b = new byte[1024];
//新建数据包对象,传入数据包.
DatagramPacket datagramPacket = new DatagramPacket(b,b.length);
//接收数据包;
datagramSocket.receive(datagramPacket);
String string = new String(datagramPacket.getData(),0,datagramPacket.getLength());
System.out.println(string);
}
}
启动接收端后,等待发送端启动
以上是关于JavaSE基础十---<网络编程>网络编程概述||通讯要素:IP和端口号,网络通信协议||关于InetAddress类||实现TCP通信||实现UDP通信的主要内容,如果未能解决你的问题,请参考以下文章
JavaSE基础(十 一 )---<线程>线程概述,创建线程,以及线程的方法,优先级,状态,用户线程,守护线程
java学习--基础知识进阶第十二天--网络编程概述UDP协议TCP协议