文章目录
- 一、网络编程基本概念
- 1、网络
- 2、计算机网络
- 3、通信协议
- 4、通信接口
- 二、网络分层
- 三、网络编程三要素
- 1、IP地址:InetAddress
- 2、端口
- 3、协议
- 3.1、网络通信协议
- 3.2、TCP/IP协议簇
- 3.3、TCP 和 UDP
- 四. TCP通信程序
- 1、TCP通信原理
- 2、TCP发送数据
- 五. UDP通信程序
- 1、 UDP通信原理
- 2、三个概念:数据包(Packet)、数据报(Datagram)和套接字(Socket)
- 2.1、数据报(Datagram)
- 2.2、套接字(Socket)
- 2.3、数据包(Packet)
- 3、 UDP发送数据
- 六、URL编程
- 1、URL类
- 2、针对HTTP协议的URLConnection类
- 3、URL下载网络资源
- 七、小结
一、网络编程基本概念
1、网络
==将不同区域的电脑连接到一起,组成局域网、城域网或广域网。==把分布在不同地理区域的计算机与专门的外部设备用通信线路互联成一个规模大、功能强的网络系统,从而使众多的计算机可以方便地互相传递信息,共享硬件、软件、数据信息等资源
2、计算机网络
是指将地理位置相同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在==网络操作系统、网络管理软件及通信协议的管理和协调下,实现资源共享和信息传递的计算机系统
3、通信协议
计算机网络中实现通信必须有一些约定即通信协议,对速率、传输代码、代码结构、传输控制步骤、出错控制等制定标准
4、通信接口
为了使两个结点之间能进行对话,必须在它们之间建立通信工具(即接口),使彼此之间能进行信息交换
接口包括两部分:
- 硬件装置:实现节点之间的信息传送
- 软件装置:规定双方进行通信的约定协议
二、网络分层
由于结点之间联系很复杂,在指定协议时,把复杂成份分解成一些简单的成份,再将他们复合起来。最常用的复合方式是层次方式,即同层间可以通信、上一层可以调用下一层,而与再下一层不发生关系
TCP/IP是一个协议族,也是按照层次划分,共四层:应用层,传输层,网络层、数据链路层
OSI网络通信协议模型,是一个参考模型,而TCP/IP协议是事实上的标准。TCP/IP协议参考了OSI模型,但是并没有严格按照OSI规定的七层标准去划分,而只划分了四层,这样会更简单点,当划分太多层时,你很难区分某个协议是属于哪个层次的
三、网络编程三要素
1、IP地址:InetAddress
要想让网络中的计算机能够互相通信,必须为计算机指定一个标识号,通过这个标识号来指定要接受数据的计算机和识别发送的计算机,而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
- IPV6:128位(16个字节),写成8个无符号整数,每个整数用四个十六进制位表示,数之间用冒号(:)分开,如:3ffe:3201:1401:1280:c8ff:fe4d:db39:1984
IP地址分类方式2:公网地址(万维网使用)和私有地址(局域网使用)。192.168.开头的就是私有址址,范围即为192.168.0.0–192.168.255.255,专门为组织机构内部使用
特点:不易记忆
2、端口
网络的通信,本质上是两个应用程序的通信。每台计算机都有很多的应用程序,那么在网络通信时,如何区别这些应用程序呢?如果说IP地址可以唯一的标识网络中的设备,那么端口号就可以唯一标识设备中的应用程序,也就是应用程序的标识。
端口号标识正在计算机上运行的进程(程序)
不同的进程有不同的端口号
被规定为一个 16 位的整数 0~65535。
端口分类:
- 公认端口:0~1023。被预先定义的服务通信占用(如:HTTP占用端口80,FTP占用端口21,Telnet占用端口23)
- 注册端口:1024~49151。分配给用户进程或应用程序。(如:Tomcat占用端口8080,MySQL占用端口3306,Oracle占用端口1521等)。
动态/私有端口:49152~65535。
端口号与IP地址的组合得出一个网络套接字:Socket。
3、协议
3.1、网络通信协议
通过计算机网络可以使多台计算机实现连接,位于同一网络中的计算机进行连接和通信时需要遵守一定的规则,这就好比在道路中行驶的汽车一定要遵守交通规则一样。在计算机网络中,这些连接和通信的规则被称为计算机网络通信协议。它对数据的传输格式、传输速率、传输步骤等做了统一规定,通信双方必须同时遵守才能完成数据交换。
问题:网络协议太复杂
计算机网络通信涉及内容很多,比如指定源地址和目标地址,加密解密,压缩
解压缩,差错控制,流量控制,路由控制,如何实现如此复杂的网络协议呢?
通信协议分层的思想
在制定协议时,把复杂成份分解成一些简单的成份,再将它们复合起来。最常
用的复合方式是层次方式,即同层间可以通信、上一层可以调用下一层,而与
再下一层不发生关系。各层互不影响,利于系统的开发和扩展。
3.2、TCP/IP协议簇
传输层协议中有两个非常重要的协议:
传输控制协议TCP(Transmission Control Protocol)
用户数据报协议UDP(User Datagram Protocol)
TCP/IP 以其两个主要协议:==传输控制协议(TCP)和网络互联协议(IP) ==而得名,实际上是一组协议,包括多个具有不同功能且互为关联的协议。
IP(Internet Protocol)协议是网络层的主要协议,支持网间互连的数据通信。
TCP/IP协议模型从更实用的角度出发,形成了高效的四层体系结构,即物理链路层、IP层、传输层和应用层。
3.3、TCP 和 UDP
TCP协议:
- 使用TCP协议前,须先建立TCP连接,形成传输数据通道
- 传输前,采用“三次握手”方式,点对点通信,是可靠的
- TCP协议进行通信的两个应用进程:客户端、服务端
- 在连接中可进行大数据量的传输
- 传输完毕,需释放已建立的连接,效率低
UDP协议:
- 将数据、源、目的封装成数据包,不需要建立连接
- 每个数据报的大小限制在64K内
- 发送不管对方是否准备好,接收方收到也不确认,故是不可靠的
- 可以广播发送
- 发送数据结束时无需释放资源,开销小,速度快
TCP三次握手
举个栗子:把客户端比作男孩,服务器比作女孩。用他们的交往来说明“三次握手”过程:
(1)男孩喜欢女孩,于是写了一封信告诉女孩:我爱你,请和我交往吧!;写完信之后,男孩焦急地等待,因为不知道信能否顺利传达给女孩。
(2)女孩收到男孩的情书后,心花怒放,原来我们是两情相悦呀!于是给男孩写了一封回信:我收到你的情书了,也明白了你的心意,其实,我也喜欢你!我愿意和你交往!;
写完信之后,女孩也焦急地等待,因为不知道回信能否能顺利传达给男孩。
(3)男孩收到回信之后很开心,因为发出的情书女孩收到了,并且从回信中知道了女孩喜欢自己,并且愿意和自己交往。然后男孩又写了一封信告诉女孩:你的心意和信我都收到了,谢谢你,还有我爱你!
女孩收到男孩的回信之后,也很开心,因为发出的情书男孩收到了。由此男孩女孩双方都知道了彼此的心意,之后就快乐地交流起来了
这就是通俗版的“三次握手”,期间一共往来了三封信也就是“三次握手”,以此确认两个方向上的数据传输通道是否正常。
为什么要进行第三次握手?
为了防止服务器端开启一些无用的连接增加服务器开销以及防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。
由于网络传输是有延时的(要通过网络光纤和各种中间代理服务器),在传输的过程中,比如客户端发起了SYN=1创建连接的请求(第一次握手)。
如果服务器端就直接创建了这个连接并返回包含SYN、ACK和Seq等内容的数据包给客户端,这个数据包因为网络传输的原因丢失了,丢失之后客户端就一直没有接收到服务器返回的数据包。
客户端可能设置了一个超时时间,时间到了就关闭了连接创建的请求。再重新发出创建连接的请求,而服务器端是不知道的,如果没有第三次握手告诉服务器端客户端收的到服务器端传输的数据的话,
服务器端是不知道客户端有没有接收到服务器端返回的信息的。
TCP四次挥手:
举个栗子:把客户端比作男孩,服务器比作女孩。通过他们的分手来说明“四次挥手”过程。
“第一次挥手”:日久见人心,男孩发现女孩变成了自己讨厌的样子,忍无可忍,于是决定分手,随即写了一封信告诉女孩。
“第二次挥手”:女孩收到信之后,知道了男孩要和自己分手,怒火中烧,心中暗骂:你算什么东西,当初你可不是这个样子的!于是立马给男孩写了一封回信:分手就分手,给我点时间,我要把你的东西整理好,全部还给你!男孩收到女孩的第一封信之后,明白了女孩知道自己要和她分手。随后等待女孩把自己的东西收拾好。
“第三次挥手”:过了几天,女孩把男孩送的东西都整理好了,于是再次写信给男孩:你的东西我整理好了,快把它们拿走,从此你我恩断义绝!
“第四次挥手”:男孩收到女孩第二封信之后,知道了女孩收拾好东西了,可以正式分手了,于是再次写信告诉女孩:我知道了,这就去拿回来!
这里双方都有各自的坚持。
女孩自发出第二封信开始,限定一天内收不到男孩回信,就会再发一封信催促男孩来取东西!
男孩自发出第二封信开始,限定两天内没有再次收到女孩的信就认为,女孩收到了自己的第二封信;若两天内再次收到女孩的来信,就认为自己的第二封信女孩没收到,需要再写一封信,再等两天……
倘若双方信都能正常收到,最少只用四封信就能彻底分手!这就是“四次挥手”。
为什么“握手”是三次,“挥手”却要四次?
TCP建立连接时之所以只需要"三次握手",是因为在第二次"握手"过程中,服务器端发送给客户端的TCP报文是以SYN与ACK作为标志位的。SYN是请求连接标志,表示服务器端同意建立连接;ACK是确认报文,表示告诉客户端,服务器端收到了它的请求报文。
即SYN建立连接报文与ACK确认接收报文是在同一次"握手"当中传输的,所以"三次握手"不多也不少,正好让双方明确彼此信息互通。
TCP释放连接时之所以需要“四次挥手”,是因为FIN释放连接报文与ACK确认接收报文是分别由第二次和第三次"握手"传输的。为何建立连接时一起传输,释放连接时却要分开传输?
建立连接时,被动方服务器端结束CLOSED阶段进入“握手”阶段并不需要任何准备,可以直接返回SYN和ACK报文,开始建立连接。
释放连接时,被动方服务器,突然收到主动方客户端释放连接的请求时并不能立即释放连接,因为还有必要的数据需要处理,所以服务器先返回ACK确认收到报文,经过CLOSE-WAIT阶段准备好释放连接之后,才能返回FIN释放连接报文。
所以是“三次握手”,“四次挥手”。
四. TCP通信程序
1、TCP通信原理
TCP通信协议是一种可靠网络协议,它在通信的两端各建立一个Socket对象,从而在通信的两端形成网络虚拟链路,一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信。
- 使用基于TCP协议的Socket网络编程实现,使用Socket对象来代表两端的通信端口
- TCP协议基于请求-响应模式,第一次主动发起的程序被称为客户端(Client)程序
- 第一次通讯中等待连接的程序被称为服务器端(Sercer)程序
Java为客户端提供了Socket类,为服务器端提供了ServerSocket类
Socket类
常用构造器
构造方法 | 说明 |
Socket(InetAddress address, int port) | 创建流套接字并将其连接到指定IP地址的指定端口号 |
Socket(String host, int port) | 创建流套接字并将其连接到指定主机上的指定端口号 |
常用方法
常用方法 | 说明 |
OutputStream getOutputStream() | 返回此套接字的输出流 |
InputStream getInputStream() | 返回此套接字的输入流 |
void shutdownOutput() | 禁用此套接字的输出流 |
ServerSocket类
常用构造器
构造方法 | 说明 |
ServerSocket(int port) | 创建绑定到指定端口的服务器套接字 |
常用方法
常用方法 | 说明 |
Socket accept() | 侦听要连接到此套接字并接受它 |
2、TCP发送数据
练习一:简单的发送和接收数据
- 服务器端
- 创建ServerSocket(int port)对象
- 在Socket上使用accept方法监听客户端的连接请求
- 阻塞、等待连接的建立
- 接收并处理请求信息
- 将处理结果返回给客户端
- 关闭流和Socket对象
- 客户端
- 创建Socket(String host, int port)对象
- 向服务器发送连接请求
- 向服务器发送服务请求
- 接受服务结果(服务响应)
- 关闭流和Socket对象
示例代码
服务端
package com.kuang.lesson02;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
//服务端
public class TcpServerDemo01 {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
ByteArrayOutputStream baos = null;
//1.我得有一个地址
try {
serverSocket = new ServerSocket(9999);
//2.等待客户端连接过来
socket = serverSocket.accept();
//3.读取客户端的消息
is = socket.getInputStream();
//管道流
baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while((len=is.read(buffer))!=-1){
baos.write(buffer,0,len);
}
System.out.println(baos.toString());
baos.close();
is.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}finally {
//关闭资源
if(baos != null){
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(baos != null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}if(baos != null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(serverSocket != null){
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
客户端
package com.kuang.lesson02;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
//客户端
public class TcpClientDemo01 {
public static void main(String[] args) {
Socket socket = null;
OutputStream os = null;
try {
//1.要知道服务器的地址
InetAddress serverIP = InetAddress.getByName("127.0.0.1");
//2.端口号
int port = 9999;
//3.创建一个socket连接
socket = new Socket(serverIP,port);
//4.发送消息IO流
os = socket.getOutputStream();
os.write("你好,欢迎学习狂神说Java".getBytes(StandardCharsets.UTF_8));
}catch (UnknownHostException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally {
if(os!=null){
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
结果如下
服务端
客户端
练习二:下载图片
- 客户端:读取发送图片
- 服务端:接收输出图片
示例代码
服务端
package com.kuang.lesson02;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
public class TcpServerDemo02 {
public static void main(String[] args) throws Exception{
//1.创建服务
ServerSocket serverSocket = new ServerSocket(9000);
//2.监听客户端的连接
Socket socket = serverSocket.accept();//阻塞式监听,会一直等待客户端
// 3.获取输入流
InputStream is = socket.getInputStream();
//4.文件输出
FileOutputStream fos = new FileOutputStream(new File("receive.jpg"));
byte[] buffer = new byte[1024];
int len;
while((len=is.read(buffer))!=-1){
fos.write(buffer,0,len);
}
//通知客户端我接收完毕了
OutputStream os = socket.getOutputStream();
os.write("我接收完毕了,你可以断开了".getBytes(StandardCharsets.UTF_8));
//关闭资源
fos.close();
is.close();
serverSocket.close();
socket.close();
}
}
客户端
package com.kuang.lesson02;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
public class TcpClientDemo02 {
public static void main(String[] args) throws Exception{
//1.创建一个socket连接
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9000);
//2.创建一个输出流
OutputStream os = socket.getOutputStream();
//3.读取文件
FileInputStream fis = new FileInputStream(new File("lin.jpg"));
//4.写入文件
byte[] buffer = new byte[1024];
int len;
while((len=fis.read(buffer))!= -1){
os.write(buffer,0,len);
}
//通知服务器,我已经结束了
socket.shutdownOutput();//我已经传输完了
//确定服务器接收完毕,才能断开连接
InputStream inputStream = socket.getInputStream();
//String byte[]
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer2 = new byte[2014];
int len2;
while((len2=inputStream.read(buffer2))!= -1){
baos.write(buffer2,0,len2);
}
System.out.println(baos.toString());
//5.关闭资源
fis.close();
os.close();
socket.close();
}
}
结果如下
服务端
客户端
五. UDP通信程序
1、 UDP通信原理
- UDP协议是一种不可靠的网络协议,它在通信的两端各建立一个Socket对象,但是这两个Socket只是发送,接收数据的对象
- 基于UDP协议的通信双方而言,没有客户端和服务器概念
Java提供了DatagramSocket类和DatagramPacket类
- DatagramSocket:用于发送或接收数据包的套接字
- DatagramPacket:数据包
DatagramSocket类
- 此类表示用于发送和接收数据报数据包的套接字
- 数据报套接字是分组传送服务的发送或接收点
常用构造器
常用构造器 | 说明 |
DatagramSocket() | 构造数据报套接字并将其绑定到本地主机上的任何可用端口 |
DatagramSocket(int port) | 构造数据报套接字并将其绑定到本地主机上的指定端口 |
常用方法
常用方法 | 说明 |
void send(DatagramPacket p) | 从此套接字发送数据报包 |
void receive(DatagramPacket p) | 从此套接字接收数据报包(阻塞式的接收) |
DatagramPacket类
- 该类表示数据报包
- 数据报包用于实现无连接分组传送服务
常用构造器
常用构造器 | 说明 |
(接收方) DatagramPacket(byte[] buf, int length) | 构造一个 DatagramPacket用于接收长度的数据包 length |
(发送方)DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port) | 构造用于发送指定长度的数据报包到指定主机的指定端口号上 |
常用方法
常用方法 | 说明 |
int getLength() | 返回要发送的数据的长度或接收到的数据的长度 |
byte[] getData() | 返回数据缓冲区 |
2、三个概念:数据包(Packet)、数据报(Datagram)和套接字(Socket)
2.1、数据报(Datagram)
数据报是通过网络传输的数据的基本单元,包含一个报头(header)和数据本身,其中报头描述了数据的目的地以及和其它数据之间的关系。数据报是完备的、独立的数据实体,该实体携带要从源计算机传递到目的计算机的信息,该信息不依赖以前在源计算机和目的计算机以及传输网络间交换。
UDP数据报的长度是指包括报头和数据部分在内的总字节数,其中报头长度固定,数据部分可变。数据报的最大长度根据操作环境的不同而各异。从理论上说,包含报头在内的数据报的最大长度为65535字节(64K)
我们在用Socket编程时,UDP协议要求包小于64K,TCP没有限定
2.2、套接字(Socket)
所谓套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象
从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议根进行交互的接口
2.3、数据包(Packet)
包(Packet)是TCP/IP协议通信传输中的数据单位,一般也称“数据包”
3、 UDP发送数据
练习一:简单的信息发送
- 创建发送端的Socket对象(DatagramSocket)。如果没有指定端口,发送到本地主机所有可用端口(不常用),这里可以采用指定端口构造方法
- 创建数据,并把数据封装成DatagramPacket包裹,数据一定要转成字节数组,同时需要指定IP地址和端口
- 调用DatagraSocket对象的方法发送数据包裹
- 关闭发送端,释放资源
示例代码
服务端
package com.kuang.lesson03;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
//还是要等待客户端的连接
public class UdpserverDemo01 {
public static void main(String[] args) throws Exception{
//开放端口
DatagramSocket socket = new DatagramSocket(9990);
//接收数据包
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length);
socket.receive(packet);//阻塞接收
System.out.println(packet.getAddress().getHostAddress());
System.out.println(new String(packet.getData(),0,packet.getLength()));
//关闭连接
socket.close();
}
}
客户端
package com.kuang.lesson03;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.nio.charset.StandardCharsets;
//不需要连接服务器
public class UdpClientDemo01 {
public static void main(String[] args) throws Exception{
//1.建立一个Socket
DatagramSocket socket = new DatagramSocket();
//2.建个包
String msg = "你好啊,服务器!";
//3.发送给谁
InetAddress localhost = InetAddress.getByName("localhost");
int port = 9990;
//数据,数据的长度起始,要发送给谁
DatagramPacket packet = new DatagramPacket(msg.getBytes(StandardCharsets.UTF_8),msg.getBytes(StandardCharsets.UTF_8).length,localhost,port);
//4.发送包
socket.send(packet);
//5.关闭流
socket.close();
}
}
结果如下
服务端
客户端
练习二:一对一线上咨询
需求:
- 完成在线咨询功能
- 学生和咨询师在线一对一交流
- 加入多线程,可以双向交流
- 聊天终止条件为输入"bye"
示例代码
客户端
//客户端
public class TalkSend implements Runnable {
private DatagramSocket client;
private BufferedReader reader;
private String toIP; // 对方的IP地址
private int toPort; // 对方的端口
public TalkSend(int port, String toIP, int toPort) {
this.toIP = toIP;
this.toPort = toPort;
try {
client = new DatagramSocket(port);
reader = new BufferedReader(new InputStreamReader(System.in));
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true) {
String data;
try {
data = reader.readLine();
byte[] datas = data.getBytes();
// 封装成DatagramPacket包裹,指定目的地
DatagramPacket packet = new DatagramPacket(datas, 0, datas.length,
new InetSocketAddress(this.toIP, this.toPort));
client.send(packet);
// 终止条件
if (data.equals("bye")) {
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 释放资源
client.close();
}
}
服务端
package com.kuang.lesson03;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class TalkReceive implements Runnable{
DatagramSocket socket = null;
private int port;
private String msgFrom;
public TalkReceive(int port,String msgFrom) {
this.port = port;
this.msgFrom = msgFrom;
try {
socket = new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true) {
try {
//准备接收包裹
byte[] container = new byte[1024];
DatagramPacket packet = new DatagramPacket(container, 0, container.length);
socket.receive(packet);//阻塞式接收包裹
//断开连接 bye
byte[] data = packet.getData();
String receiveData = new String(data, 0, data.length);
System.out.println(msgFrom + ":" + receiveData);
if (receiveData.equals("bye")) {
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
socket.close();
}
}
学生方
package com.kuang.lesson03;
public class TalkStudent {
public static void main(String[] args) {
//开启两个线程
new Thread(new TalkSend(7777,"localhost",9999)).start();
new Thread(new TalkReceive(8888,"老师")).start();
}
}
老师方
package com.kuang.lesson03;
public class TalkTeacher {
public static void main(String[] args) {
new Thread(new TalkSend(5555,"localhost",8888)).start();
new Thread(new TalkReceive(9999,"学生")).start();
}
}
结果如下
学生方
老师方
这里强调一下,UDP编程属于底层开发,是网络编程,而不是网页编程,网页编程中这种Socket已经被实现
六、URL编程
1、URL类
URL(Uniform Resource Locator):统一资源定位符,它表示 Internet 上某一资源的地址。
它是一种具体的URI,即URL可以用来标识一个资源,而且还指明了如何locate这个资源。
通过 URL 我们可以访问 Internet 上的各种网络资源,比如最常见的 www,ftp 站点。浏览器通过解析给定的 URL 可以在网络上查找相应的文件或其他资源。
URL的基本结构由5部分组成:
<传输协议>://<主机名>:<端口号>/<文件名>#片段名?参数列表
例如:
- http://192.168.1.100:8080/helloworld/index.jsp#a?username=shkstart&password=123
- #片段名:即锚点,例如看小说,直接定位到章节
- 参数列表格式:参数名=参数值&参数名=参数值…
URL类构造器
public URL (String spec) | 通过一个表示URL地址的字符串可以构造一个URL对象 |
public URL(URL context, String spec) | 通过基 URL 和相对 URL 构造一个 URL 对象 |
URL类常用方法
public String getProtocol( ) | 获取该URL的协议名 |
public String getHost( ) | 获取该URL的主机名 |
public String getPort( ) | 获取该URL的端口号 |
public String getPath( ) | 获取该URL的文件路径 |
public String getFile( ) | 获取该URL的文件名 |
public String getQuery( ) | 获取该URL的查询名 |
2、针对HTTP协议的URLConnection类
URL的方法 openStream():能从网络上读取数据
若希望输出数据,例如向服务器端的 CGI (公共网关接口-Common Gateway Interface-的简称,是用户浏览器和服务器端的应用程序进行连接的接口)程序发送一些数据,则必须先与URL建立连接,然后才能对其进行读写,此时需要使用URLConnection 。
URLConnection:表示到URL所引用的远程对象的连接。当与一个URL建立连接时,首先要在一个 URL 对象上通过方法 openConnection() 生成对应的 URLConnection对象。如果连接过程失败,将产生IOException。
- URL netchinaren = new URL (“http://www.atguigu.com/index.shtml”);
- URLConnectonn u = netchinaren.openConnection( );
通过URLConnection对象获取的输入流和输出流,即可以与现有的CGI程序进行交互。
3、URL下载网络资源
需求:
- 自建了一个tomcat网站
- 下载该网站中的资源
示例代码
package com.kuang.lesson04;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class UrlDown {
public static void main(String[] args) throws Exception{
URL url = new URL("http://localhost:8080/qinjiang/SecurityFile.txt");
//2.连接到这个资源 HTTP
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
FileOutputStream fos = new FileOutputStream("SecurityFile.txt");
byte[] buffer = new byte[1024];
int len;
while((len = inputStream.read(buffer)) != -1){
fos.write(buffer,0,len);
}
fos.close();
inputStream.close();
urlConnection.disconnect();
}
}
结果如下
注意:这里字体格式没有改成UFT-8所以乱码
七、小结
- 位于网络中的计算机具有唯一的IP地址,这样不同的主机可以互相区分
- 客户端-服务器是一种最常见的网络应用程序模型。服务器是一个为其客户端提供某种特定服务的硬件或软件。客户机是一个用户应用程序,用于访问某台服务器提供的服务。端口号是对一个服务的访问场所,它用于区分同一物理计算机上的多个服务。套接字用于连接客户端和服务器,客户端和服务器之间的每个通信会话使用一个不同的套接字。TCP协议用于实现面向连接的会话
- Java 中有关网络方面的功能都定义在 java.net 程序包中。Java 用 InetAddress 对象表示 IP 地址,该对象里有两个字段:主机名(String) 和 IP 地址(int)
- 类 Socket 和 ServerSocket 实现了基于TCP协议的客户端-服务器程序。Socket是客户端和服务器之间的一个连接,连接创建的细节被隐藏了。这个连接提供了一个安全的数据传输通道,这是因为 TCP 协议可以解决数据在传送过程中的丢失、损坏、重复、乱序以及网络拥挤等问题,它保证数据可靠的传送。
- 类 URL 和 URLConnection 提供了最高级网络应用。URL 的网络资源的位置来同一表示
Internet 上各种网络资源。通过URL对象可以创建当前应用程序和 URL 表示的网络资源之
间的连接,这样当前程序就可以读取网络资源数据,或者把自己的数据传送到网络上去。