Java网络编程的API都在Java.net包里面。
网络编程三要素:
1.IP
2.端口
3.协议(TCP、UDP)
一、IP
package com.StadyJava.day16; import java.net.InetAddress; import java.net.UnknownHostException; public class SetDemo { public static void main(String[] args) throws UnknownHostException { //通过主机名或者域名来获取IP,我这里根据域名获取 InetAddress ip=InetAddress.getByName("www.wikipedia.org"); System.out.println(ip); //获取主机名 System.out.println(ip.getHostName()); //获取IP System.out.println(ip.getHostAddress()); } }
就这几个方法,执行结果
二、端口
什么是端口?端口就是一台设备与外面交流的接口,有虚拟端口和物理端口。一个IP地址有65536个端口可用。
端口号这么多,大致可以分为以下3大类
那怎么查看一台电脑上的端口呢?推荐一个软件CurrPorts,这个软件的效果如下图:
三、协议
有了IP,我们就找到了那台设备主机,有了端口,我们就可以有了通道去和那台主机进行沟通。那么现在问题来了,怎么沟通呢?我说中国话,那个人说德语。这怎么办?协议应运而生!规定,某个协议下必须说相同的话才可以。例如传输层可以使用TCP协议,也可以使用UDP协议,在这个协议下的语言是想通的。协议有很多,如下图。但是我们这里只需要学习TCP和UDP
网络编程,我们经常听到URL这个词,那这个是什么意思呢?URI和URL都表示一个路径
我们来看看如何创建一个URL对象,这个代码不能运行,需要你安装Tomcat来充当一台服务器才可以。
package com.StadyJava.day22; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Scanner; public class UrlDemo { public static void main(String[] args) throws Exception{ //创建URL对象,参数有4个,分别是协议、主机名、端口号、资源路径 URL url=new URL("http","localhost",8080,"/index.jsp"); //创建完URL对象之后要开启链接 URLConnection con = url.openConnection(); //可以读取流,也可以写入流,这里我们读取流的内容 InputStream in = con.getInputStream(); //获取到URL资源的读取流了,可以进行操作 //打印操作 Scanner scanner=new Scanner(in); while (scanner.hasNext()){ String line=scanner.nextLine(); System.out.println(line); } scanner.close(); //下载操作,Files类只有Java1.7版本以上才有 Files.copy(in, Paths.get("index.html")); } }
信息在传输的时候,总不能明文传输吧,这样不安全。所以有了编码解码这一说,把我们的信息加个密,和间谍发的密文是一样的。
package com.StadyJava.day22; import java.lang.*; import java.net.URLDecoder; import java.net.URLEncoder; public class UrlDemo { public static void main(String[] args) throws Exception { //编码解码 String ret=URLEncoder.encode("蜀云泉真帅 shuyunquan 9","UTF-8"); System.out.println(ret); //解码 String msg=URLDecoder.decode(ret,"UTF-8"); System.out.println(msg); } }
来模拟一个TCP的例子
TCP服务端:
package com.StadyJava.day22; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; public class TCPServer { public static void main(String[] args) throws Exception { //创建服务端,指定端口为8888 ServerSocket server=new ServerSocket(8888); System.out.println("服务端已经开启"); //接收链接而来的客户端 Boolean accept=true; while (accept){ Socket client=server.accept(); System.out.println("链接过来的客户端ip是"+client.getInetAddress()); PrintStream out=new PrintStream(client.getOutputStream()); out.println("服务端:客户端,你好吗?"); out.close(); } server.close(); } }
TCP客户端:
package com.StadyJava.day22; import java.net.Socket; import java.util.Scanner; public class TCPClient { public static void main(String[] args) throws Exception { //创建客户端 Socket client=new Socket("localhost",8888); System.out.println("客户端已经开启"); //获取客户端的输入流,也就是服务端发的消息 Scanner sc=new Scanner(client.getInputStream()); while (sc.hasNext()){ String msg=sc.nextLine(); System.out.println(msg); } sc.close(); client.close(); } }
TCP是通过三次握手来建立连接的,发送的数据都是流的形式,所以可以看到都是getInputStream()和OutStream之类的流
UDP是通过数据报包的形式来传输数据的,其实数据报包的底层也是数据流,来看看UDP的代码例子
发送端:
package com.StadyJava.day22; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class UDPSender { public static void main(String[] args) throws Exception { String msg="UDP发送器"; //UDP发送方式是DatagramSocket,new对象的时候要指定端口 DatagramSocket send=new DatagramSocket(8000); //创建数据报包,发送数据 DatagramPacket pt=new DatagramPacket(msg.getBytes(),msg.getBytes().length,InetAddress.getLocalHost(),8001); //发送 send.send(pt); } }
接收端:
package com.StadyJava.day22; import java.net.DatagramPacket; import java.net.DatagramSocket; public class UDPReceive { public static void main(String[] args) throws Exception{ //创建DatagramSocket对象,指定端口 DatagramSocket receive=new DatagramSocket(8001); //创建一个缓冲数组,用来接收数据。因为DatagramPacket接收数据的时候需要缓冲数组 byte[] buffer=new byte[1024]; //创建数据报包,来接收数据 DatagramPacket pt=new DatagramPacket(buffer,1024); //接收数据 receive.receive(pt); //把接收的数据从byte数组传化为String类型的字符串 String msg=new String(pt.getData(),0,pt.getLength()); System.out.println(msg); } }