第1关:URL类与InetAddress类
任务描述
本关任务:了解网络编程基础知识。
相关知识
为了完成本关任务,你需要掌握:1.URL;2.InetAddress。
URL
统一资源定位符(Uniform Resource Locator,缩写为URL)是对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址。 互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。
URL可以分为如下几个部分:
protocol://host:port/path?query#fragment
HTTP 协议的 URL 实例如下:
http://www.runoob.com/index.html?language=cn#javase
- 协议为(protocol):
http
- 主机为(host:port):
www.runoob.com
- 端口号为(port):
80
,以上URL实例并未指定端口,因为 HTTP 协议默认的端口号为80
- 文件路径为(path):
/index.html
- 请求参数(query):
language=cn
- 定位位置(fragment):
javase
,定位到网页中id
属性为javase
的HTML
元素位置。
URL对象
java.net
包中的 URL
类是对统一资源定位符的抽象,使用 URL
创建对象的应用程序称作客户端程序。一个URL
对象通常包含最基本的三部分信息:协议、地址和资源。
URL
对象定义public URL(String spec) throws MalformedURLException
public URL(String protocol, String host, String file) throws MalformedURLException
- 读取
URL
中的资源:URL
对象调用InputStream openStream()
方法返回一个输入流,该输入流指向URL
对象所包含的资源。通过该输入流可以将服务器上的资源信息读入到客户端。
InetAddress 类
InetAddress
类是Java对IP
地址的封装,在java.net
中有许多类都使用到了InetAddress
类,包括:ServerSocket
,Socket
,DatagramSocket
等等。 InetAddress
对域名进行解析是使用本地机器配置或者网络命名服务(如域名系统(Domain Name System,DNS
)和网络信息服务(Network Information Service,NIS
))来实现。对于DNS
来说,本地需要向DNS
服务器发送查询的请求,然后服务器根据一系列的操作,返回对应的IP
地址。 为了提高效率,通常本地会缓存一些主机名与IP
地址的映射,这样访问相同的地址,就不需要重复发送DNS
请求了。在java.net.InetAddress
类同样采用了这种策略。默认情况下,会缓存一段有限时间的映射,对于主机名解析不成功的结果,会缓存非常短的时间(10秒)来提高性能。
该类没有构造器,可以通过它的两个静态方法来获取InetAddress
的实例。
getByName(String s)
:获取InetAddress
对象
- 用域名作为
getByName()
和getAllByName()
方法的参数得到的InetAddress
对象,该对象会得到这个域名,当调用getHostName()
时,就无需再访问DNS
服务器,而是直接将这个域名返回。 - 用IP地址作为
getByName()
,getAllByName()
,getByAddress()
方法的参数,创建InetAddress
对象时,并不需要访问DNS
服务器。因此,通过DNS
服务器查找域名的工作就由getHostName()
方法来完成。如果IP
地址不存在或DNS
服务器不允许进行IP
地址和域名映射,就返回这个IP
地址。 - 用主机名作为参数创建InetAddress对象。
- 静态方法
getLocalHost()
获取本机的InetAddress
。如果获取不到(可能是安全问题),就会返回地址:127.0.0.1
和 主机名:localhost
。
getByAddress(byte[] addr)
:根据源IP
地址来获取InetAddress
对象。
编程要求
根据提示,使用URL
类和InetAddress
类编程,在右侧编辑器 Begin-End
补充代码。
- 使用
java.net
的URL
类获取URL
的各个部分参数 - 使用
InetAddress
类的getAllByName()
方法,输出百度主机的所有地址
测试说明
平台会对你编写的代码进行测试:
测试输入:
预期输出:
协议为:http
主机名:www.runoob.com
路径:/index.html
端口:-1
请求参数:language=cn
www.baidu.com/180.101.50.188
www.baidu.com/180.101.49.242
注明:百度主机输出结果的顺序不一致时,可以多评测几次。
代码实现
package step1;import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;public class Step1Test
{public static void main(String[] args){// URL地址:http://www.runoob.com/index.html?language=cn#javase// 1. 要求输出:协议、主机名、路径、端口、请求参数// ********** Begin **********try{URL url = new URL("http://www.runoob.com/index.html?language=cn#javase");System.out.println("协议为:" + url.getProtocol());System.out.println("主机名:" + url.getHost());System.out.println("路径:" + url.getPath());System.out.println("端口:" + url.getPort());System.out.println("请求参数:" + url.getQuery());}catch (MalformedURLException e){e.printStackTrace();}// 2. 输出百度的所有主机地址// ********** End **********try{InetAddress[] addresses = InetAddress.getAllByName("www.baidu.com");// for (InetAddress address : addresses)// {// System.out.println("www.baidu.com/" + address.getHostAddress());// }System.out.println("www.baidu.com/" + addresses[0].getHostAddress());System.out.println("www.baidu.com/" + addresses[1].getHostAddress());}catch (UnknownHostException e){e.printStackTrace();}}
}
第2关:TCP Socket通信
任务描述
本关任务:编写程序实现基于TCP/IP协议的Socket通信。
相关知识
为了完成本关任务,你需要掌握:1.TCP/IP协议,2.Socket套接字,3.基于TCP/IP协议的Socket通信。
OSI参考模型和TCP/IP模型
计算机网络市场刚刚兴起时,许多计算机生产厂商都积极推出自己公司独创的网络。由于这些网络都不互通,导致使用某种网络的用户如果在后续扩展网络时必须继续使用原计算机厂商的设备。这样使得市场上各自保护现象很严重。基于上述原因,国际标准化组织制定了一套标准,只要大家都遵循这套标准,那么各自的产品就可以相互兼容,这套标准就叫OSI参考模型。正所谓“没有规矩不成方圆”。 OSI参考模型分为7层,分别是物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。分层有助于把网络操作分成不太复杂的单元,分工合作,责任明确。
TCP/IP模型严格来说是一个四层的体系结构。应用层、传输层、网络层和数据链路层都包含其中。虽然它有四层网络模型层数,只是因为在TCP/IP模型中TCP模型和IP模型最具代表性,所以被称为TCP/IP模型。TCP/IP模型具有数据的时新性、具有数据的时新性和传输技术的先进易用性。
TCP/IP协议
从字面意义上讲,有人可能会认为 TCP/IP 是指 TCP 和 IP 两种协议。实际生活当中有时也确实就是指这两种协议。然而在很多情况下,它只是利用 IP 进行通信时所必须用到的协议群的统称。具体来说,IP 或 ICMP、TCP 或 UDP、TELNET 或 FTP、以及 HTTP 等都属于 TCP/IP 协议。它们与 TCP 或 IP 的关系紧密,是互联网必不可少的组成部分。
Socket套接字
我们可以把所有渴望建立连接的对象都理解为套接字。要想建立网络连接,就像插头与插座套接在一起,而“字”则代表了可交互的有序指令串。Socket的引入就是为了解决不同计算机之间进程间相互通信的问题。
IP层的IP地址可以唯一标识Internet上的计算机,而TCP层协议和端口号可以唯一标识计算机上运行的一个进程,这样我们可以利用“IP地址+协议+端口号”来唯一标识网络中的一个进程。IP地址与端口号的组合可以得出一个Socket即网络套接字。Socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作,抽象为几个简单的接口供应用层调用,以实现进程在网络中的通信。能够唯一标识网络中的进程后,就可以利用Socket进行通信了。
Socket通信模型
具体地,Socket通信的过程,它通常分为三个步骤,分别是:服务器监听,客户端请求,连接确认。在 Java 语言中,需要使用 java.net 包中的ServerSocket类和Socket类来实现。
编程要求
请编写程序实现基于TCP/IP协议的Socket通信过程。 服务器端程序平台已经编写完毕。需要你根据提示,在右侧编辑器补充客户端代码。
- 服务器端开放: IP地址:
127.0.0.1
端口号:8889
- 客户端发送数据:
Hello Server!
测试说明
服务器端代码:
public class Server
{public static void main(String[] args) {try {ServerSocket ss = new ServerSocket(8889);System.out.println("启动服务器....");Socket s = ss.accept();BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));//读取客户端发送来的消息String mess = br.readLine();System.out.println("客户端:" + mess);ss.close();} catch (IOException e) {e.printStackTrace();}}
}
平台会对你编写的代码进行测试:
测试输入:
启动服务器…
客户端:测试客户端与服务器通信:Hello Server!
开始你的任务吧,祝你成功!
代码实现
package step2;import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;/*** 描述:描述:第2关:TCP Socket通信** @author 为一道彩虹*/
public class Client
{public static void main(String[] args){try {// 连接到IP地址为127.0.0.1,端口号为8889的服务器Socket socket = new Socket("127.0.0.1", 8889);// 获取socket的输出流OutputStream outputStream = socket.getOutputStream();// 使用PrintWriter包装输出流,方便发送字符串PrintWriter writer = new PrintWriter(new OutputStreamWriter(outputStream, "UTF-8"), true);// 发送数据到服务器writer.println("测试客户端与服务器通信:Hello Server!");// 关闭连接socket.close();}catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
}
第3关:UDP Socket通信
任务描述
本关任务:编写程序实现基于UDP协议的Socket通信。
相关知识
为了完成本关任务,你需要掌握:1.UDP协议,2.Socket套接字,3.基于UDP协议的Socket通信。
UDP协议
基于UDP的通信和基于TCP的通信不同,基于UDP的信息传递更快,但不提供可靠性保证。即数据在传输时,用户无法知道数据能否正确到达目的地主机,也不能确定数据到达目的地的顺序是否和发送的顺序相同。UDP通信比作邮递信件。
基于UDP通信的基本模式:
- 将数据打包,称为数据包,然后将数据包发往目的地。
- 接收别人发来的数据包,然后查看数据包中的内容。
Socket套接字
我们可以把所有渴望建立连接的对象都理解为套接字。要想建立网络连接,就像插头与插座套接在一起,而“字”则代表了可交互的有序指令串。Socket的引入就是为了解决不同计算机之间进程间相互通信的问题。
IP层的IP地址可以唯一标识Internet上的计算机,而TCP层协议和端口号可以唯一标识计算机上运行的一个进程,这样我们可以利用“IP地址+协议+端口号”来唯一标识网络中的一个进程。IP地址与端口号的组合可以得出一个Socket即网络套接字。Socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作,抽象为几个简单的接口供应用层调用,以实现进程在网络中的通信。能够唯一标识网络中的进程后,就可以利用Socket进行通信了。
UDP Socket通信模型
- 用
DatagramPacket
类将数据打包,有两个构造方法:
public DatagramPacket(byte[] data, int length, InetAddress address, int port)
;public DatagramPacket(byte[] data, int offset, int length, InetAddress address, int port)
;
- 用
DatagramSocket
类的不带参数的构造方法DatagramSocket()
创建一个对象,该对象负责发送数据包。
DatagramSocket mail_out = new DatagramSocket();
Mail_out.send(data_pack);
- 用
DatagramSocket
类的另一个构造方法DatagramSocket(int port)
创建一个对象,其中的参数必须和待接收数据包的发送端口号相同。
DatagramSocket mail_in = new DatagramSocket(5666);
- 然后对象
mail_in
使用方法receive(DatagramPacket pack)
接收数据包。必须预备一个数据包以便接收数据包。这时需要使用DatagramPacket
类的另外一个构造方法DatagramPacket(byte[] data, int length)
创建一个数据包。
byte[] data = new byte[100];
int length = 90;
DatagramPacket pack = new DatagramPacket(data, length);
mail_in.receive(pack);
编程要求
请编写程序实现基于UDP协议的Socket通信过程。 客户端程序平台已经编写完毕。需要你根据提示,在右侧编辑器补充服务器端代码。 服务器端开放:
IP地址:127.0.0.1
或者localhost
端口号:12345
用于接收从客户端发送过来的数据:
用户名:admin;密码:123
测试说明
客户端代码:
public class UDPClient
{public static void main(String[] args) throws IOException {/** 向服务器端发送数据*/// 1.定义服务器的地址、端口号、数据InetAddress address = InetAddress.getByName("localhost");int port = 12345;byte[] data = "用户名:admin;密码:123".getBytes();// 2.创建数据报,包含发送的数据信息DatagramPacket packet = new DatagramPacket(data, data.length, address, port);// 3.创建DatagramSocket对象DatagramSocket socket = new DatagramSocket();// 4.向服务器端发送数据报socket.send(packet);// 5.关闭资源socket.close();}
}
平台会对你编写的代码进行测试:
测试输入:
预期输出:
****服务器端已经启动,等待客户端发送数据
我是服务器,客户端说:用户名:admin;密码:123
开始你的任务吧,祝你成功!
代码实现
package step3;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;public class UDPServer
{public static void main(String[] args) throws IOException{/** 接收客户端发送的数据*/// 1.创建服务器端DatagramSocket,指定端口DatagramSocket socket = new DatagramSocket(12345);// 2.创建数据报,用于接收客户端发送的数据// 创建字节数组,指定接收的数据包的大小1024byte[] receiveData = new byte[1024];DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);System.out.println("****服务器端已经启动,等待客户端发送数据");// 3.接收客户端发送的数据socket.receive(receivePacket);// 4.读取数据String receivedMessage = new String(receivePacket.getData(), 0, receivePacket.getLength());System.out.println("我是服务器,客户端说:" + receivedMessage);// 5.关闭资源socket.close();}
}
先赞后看,养成习惯!!!^ _ ^ ❤️ ❤️ ❤️
码字不易,大家的支持就是我的坚持下去的动力。点赞后不要忘了关注我哦!