Java基础—网络编程
一、网络编程概述
1、计算机网络
2、网络编程
就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换。
3、网络模型
网络模型一般是指OSI(Open System Interconnection开放系统互连)参考模型或者TCP/IP参考模型。
2、路由器实现将数据包发送到指定的地点。
3、应用软件之间通信的过程就是层与层之间封包、解封包的过程。
二、网络编程三要素
网络模型说完了,我们要进行通讯,需要哪些要素呢?
比如说:我要跟你说话.
第一个条件:我要先找到你 (IP)
第二个条件:你得有接收数据的地方 耳朵 (端口)
第三个条件:我跟你说话,你能接收到,咱按什么方式接收啊,我说英文你懂吗,说韩文你懂吗,不懂是吧,所以我还是说中文把.(协议)
1、IP地址:InetAddress
② String getHostName():获取此 IP 地址的主机名。
③ String getHostAddress():返回 IP 地址字符串
1 package cn.itcast_01; 2 3 import java.net.InetAddress; 4 import java.net.UnknownHostException; 5 6 public class InetAddressDemo { 7 public static void main(String[] args) throws UnknownHostException { 8 // public static InetAddress getByName(String host) 9 // InetAddress address = InetAddress.getByName("liuyi"); 10 // InetAddress address = InetAddress.getByName("192.168.12.92"); 11 InetAddress address = InetAddress.getByName("192.168.12.63"); 12 13 // 获取两个东西:主机名,IP地址 14 // public String getHostName() 15 String name = address.getHostName(); 16 // public String getHostAddress() 17 String ip = address.getHostAddress(); 18 System.out.println(name + "---" + ip); 19 } 20 }
运行结果:
2、端口号
正在运行的程序的标识,用于标识进程的逻辑地址,不同进程的标识。有效端口:0~65535,其中0~1024系统使用或保留端口。
B:用于标识进程的逻辑地址,不同进程的标识
C:有效端口:0~65535,其中0~1024系统使用或保留端口。
3、传输协议
(2) TCP建立连接,形成传输数据的通道;在连接中进行大数据量传输;通过三次握手完成连接,是可靠协议;必须建立连接,效率会稍低
(3) UDP和TCP的特点
举例:聊天留言,在线视频,视频会议,发短信,邮局包裹。
② TCP:面向连接;安全可靠效率稍低;通过三次握手确保连接的建立。
举例:下载,打电话,QQ聊天(你在线吗,在线,就回应下,就开始聊天了)
4、域名解析
三、Socket套接字
1、Socket套接字:
2、Socket原理机制:
(1) 通信的两端都有Socket。
(2) 网络通信其实就是Socket间的通信。
(3) 数据在两个Socket间通过IO传输。
3、Socket机制图解
四、UDP编程
1、UDP传输
(2) 建立发送端,接收端。
(3) 建立数据包。
(4) 调用Socket的发送接收方法。
(5) 关闭Socket。
(6) 发送端与接收端是两个独立的运行程序。
2、DatagramSocket
(2) 数据报套接字是包投递服务的发送或接收点。每个在数据报套接字上发送或接收的包都是单独编址和路由的。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。
(3) 在 DatagramSocket 上总是启用 UDP 广播发送。为了接收广播包,应该将 DatagramSocket 绑定到通配符地址。在某些实现中,将 DatagramSocket 绑定到一个更加具体的地址时广播包也可以被接收。
② DatagramSocket(int port, InetAddress laddr):创建数据报套接字,将其绑定到指定的本地地址。
② 将要发送的数据封装成数据包
③ 通过udp的socket服务,将数据包发送出
④ 关闭资源
1 package cn.itcast_02; 2 3 import java.io.IOException; 4 import java.net.DatagramPacket; 5 import java.net.DatagramSocket; 6 import java.net.InetAddress; 7 /* 8 * UDP协议发送数据: 9 * A:创建发送端Socket对象 10 * B:创建数据,并把数据打包 11 * C:调用Socket对象的发送方法发送数据包 12 * D:释放资源 13 */ 14 public class SendDemo { 15 public static void main(String[] args) throws IOException { 16 // 创建发送端Socket对象 17 // DatagramSocket() 18 DatagramSocket ds = new DatagramSocket(); 19 20 // 创建数据,并把数据打包 21 // DatagramPacket(byte[] buf, int length, InetAddress address, int port) 22 // 创建数据 23 byte[] bys = "hello,udp,我来了".getBytes(); 24 // 长度 25 int length = bys.length; 26 // IP地址对象 27 InetAddress address = InetAddress.getByName("192.168.12.92"); 28 // 端口 29 int port = 10086; 30 DatagramPacket dp = new DatagramPacket(bys, length, address, port); 31 32 // 调用Socket对象的发送方法发送数据包 33 // public void send(DatagramPacket p) 34 ds.send(dp); 35 36 // 释放资源 37 ds.close(); 38 } 39 }
3、DatagramPacket
(2) 数据报包用来实现无连接包投递服务。每条报文仅根据该包中包含的信息从一台机器路由到另一台机器。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。不对包投递做出保证。
(3) 构造方法
构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
构造数据报包,用来将长度为 length 偏移量为 offset 的包发送到指定主机上的指定端口号。
(4) UDP传输-接收端思路
② 通过receive方法接收数据
③ 将收到的数据存储到数据包对象中
④ 通过数据包对象的功能来完成对接收到数据进行解析.
⑤ 可以对资源进行关闭
1 package cn.itcast_02; 2 3 import java.io.IOException; 4 import java.net.DatagramPacket; 5 import java.net.DatagramSocket; 6 import java.net.InetAddress; 7 8 /* 9 * UDP协议接收数据: 10 * A:创建接收端Socket对象 11 * B:创建一个数据包(接收容器) 12 * C:调用Socket对象的接收方法接收数据 13 * D:解析数据包,并显示在控制台 14 * E:释放资源 15 */ 16 public class ReceiveDemo { 17 public static void main(String[] args) throws IOException { 18 // 创建接收端Socket对象 19 // DatagramSocket(int port) 20 DatagramSocket ds = new DatagramSocket(10086); 21 22 // 创建一个数据包(接收容器) 23 // DatagramPacket(byte[] buf, int length) 24 byte[] bys = new byte[1024]; 25 int length = bys.length; 26 DatagramPacket dp = new DatagramPacket(bys, length); 27 28 // 调用Socket对象的接收方法接收数据 29 // public void receive(DatagramPacket p) 30 ds.receive(dp); // 阻塞式 31 32 // 解析数据包,并显示在控制台 33 // 获取对方的ip 34 // public InetAddress getAddress() 35 InetAddress address = dp.getAddress(); 36 String ip = address.getHostAddress(); 37 // public byte[] getData():获取数据缓冲区 38 // public int getLength():获取数据的实际长度 39 byte[] bys2 = dp.getData(); 40 int len = dp.getLength(); 41 String s = new String(bys2, 0, len); 42 System.out.println(ip + "传递的数据是:" + s); 43 44 // 释放资源 45 ds.close(); 46 } 47 }
4、UDP案例
package cn.itcast_04; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; /* * 数据来自于键盘录入 * 键盘录入数据要自己控制录入结束。 */ public class SendDemo { public static void main(String[] args) throws IOException { // 创建发送端的Socket对象 DatagramSocket ds = new DatagramSocket(); // 封装键盘录入数据 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String line = null; while ((line = br.readLine()) != null) { if ("886".equals(line)) { break; } // 创建数据并打包 byte[] bys = line.getBytes(); // DatagramPacket dp = new DatagramPacket(bys, bys.length, // InetAddress.getByName("192.168.12.92"), 12345); DatagramPacket dp = new DatagramPacket(bys, bys.length, InetAddress.getByName("192.168.12.255"), 12345); // 发送数据 ds.send(dp); } // 释放资源 ds.close(); } }
1 package cn.itcast_04; 2 3 import java.io.IOException; 4 import java.net.DatagramPacket; 5 import java.net.DatagramSocket; 6 7 /* 8 * 多次启动接收端: 9 * java.net.BindException: Address already in use: Cannot bind 10 * 端口被占用。 11 */ 12 public class ReceiveDemo { 13 public static void main(String[] args) throws IOException { 14 // 创建接收端的Socket对象 15 DatagramSocket ds = new DatagramSocket(12345); 16 17 while (true) { 18 // 创建一个包裹 19 byte[] bys = new byte[1024]; 20 DatagramPacket dp = new DatagramPacket(bys, bys.length); 21 22 // 接收数据 23 ds.receive(dp); 24 25 // 解析数据 26 String ip = dp.getAddress().getHostAddress(); 27 String s = new String(dp.getData(), 0, dp.getLength()); 28 System.out.println("from " + ip + " data is : " + s); 29 } 30 31 // 释放资源 32 // 接收端应该一直开着等待接收数据,是不需要关闭 33 // ds.close(); 34 } 35 }
运行结果:
五、TCP编程
1、TCP传输
(2) 建立客户端和服务器端
(3) 建立连接后,通过Socket中的IO流进行数据的传输
(4) 关闭socket
(5) 同样,客户端与服务器端是两个独立的应用程序。
2、Socket
② 如果连接建立成功,就表明,已经建立了数据传输的通道.就可以在该通道通过IO进行数据的读取和写入.该通道称为Socket流,Socket流中既有读取流,也有写入流.
③ 通过Socket对象的方法,可以获取这两个流
④ 通过流的对象可以对数据进行传输
⑤ 如果传输数据完毕,关闭资源
1 package cn.itcast_06; 2 3 import java.io.IOException; 4 import java.io.OutputStream; 5 import java.net.Socket; 6 7 /* 8 * TCP协议发送数据: 9 * A:创建发送端的Socket对象 10 * 这一步如果成功,就说明连接已经建立成功了。 11 * B:获取输出流,写数据 12 * C:释放资源 13 * 14 * 连接被拒绝。TCP协议一定要先看服务器。 15 * java.net.ConnectException: Connection refused: connect 16 */ 17 public class ClientDemo { 18 public static void main(String[] args) throws IOException { 19 // 创建发送端的Socket对象 20 // Socket(InetAddress address, int port) 21 // Socket(String host, int port) 22 // Socket s = new Socket(InetAddress.getByName("192.168.12.92"), 8888); 23 Socket s = new Socket("192.168.12.92", 8888); 24 25 // 获取输出流,写数据 26 // public OutputStream getOutputStream() 27 OutputStream os = s.getOutputStream(); 28 os.write("hello,tcp,我来了".getBytes()); 29 30 // 释放资源 31 s.close(); 32 } 33 }
3、ServerSocket
③ 通过客户端的获取流对象的方法,读取数据或者写入数据
④ 如果服务完成,需要关闭客户端,然后关闭服务器,但是,一般会关闭客户端,不会关闭服务器,因为服务端是一直提供服务的
1 package cn.itcast_06; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.net.ServerSocket; 6 import java.net.Socket; 7 8 /* 9 * TCP协议接收数据: 10 * A:创建接收端的Socket对象 11 * B:监听客户端连接。返回一个对应的Socket对象 12 * C:获取输入流,读取数据显示在控制台 13 * D:释放资源 14 */ 15 public class ServerDemo { 16 public static void main(String[] args) throws IOException { 17 // 创建接收端的Socket对象 18 // ServerSocket(int port) 19 ServerSocket ss = new ServerSocket(8888); 20 21 // 监听客户端连接。返回一个对应的Socket对象 22 // public Socket accept() 23 Socket s = ss.accept(); // 侦听并接受到此套接字的连接。此方法在连接传入之前一直阻塞。 24 25 // 获取输入流,读取数据显示在控制台 26 InputStream is = s.getInputStream(); 27 28 byte[] bys = new byte[1024]; 29 int len = is.read(bys); // 阻塞式方法 30 String str = new String(bys, 0, len); 31 32 String ip = s.getInetAddress().getHostAddress(); 33 34 System.out.println(ip + "---" + str); 35 36 // 释放资源 37 s.close(); 38 // ss.close(); //这个不应该关闭 39 } 40 }
4、TCP传输案例
1 package cn.itcast_08; 2 3 import java.io.BufferedReader; 4 import java.io.BufferedWriter; 5 import java.io.IOException; 6 import java.io.InputStreamReader; 7 import java.io.OutputStreamWriter; 8 import java.net.Socket; 9 10 /* 11 * 客户端键盘录入,服务器输出到控制台 12 */ 13 public class ClientDemo { 14 public static void main(String[] args) throws IOException { 15 // 创建客户端Socket对象 16 Socket s = new Socket("192.168.12.92", 22222); 17 18 // 键盘录入数据 19 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 20 // 把通道内的流给包装一下 21 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter( 22 s.getOutputStream())); 23 24 String line = null; 25 while ((line = br.readLine()) != null) { 26 // 键盘录入数据要自定义结束标记 27 if ("886".equals(line)) { 28 break; 29 } 30 bw.write(line); 31 bw.newLine(); 32 bw.flush(); 33 } 34 35 // 释放资源 36 // bw.close(); 37 // br.close(); 38 s.close(); 39 } 40 }
服务器端:
1 package cn.itcast_08; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 import java.net.ServerSocket; 7 import java.net.Socket; 8 9 public class ServerDemo { 10 public static void main(String[] args) throws IOException { 11 // 创建服务器Socket对象 12 ServerSocket ss = new ServerSocket(22222); 13 14 // 监听客户端连接 15 Socket s = ss.accept(); 16 17 // 包装通道内容的流 18 BufferedReader br = new BufferedReader(new InputStreamReader( 19 s.getInputStream())); 20 String line = null; 21 while ((line = br.readLine()) != null) { 22 System.out.println(line); 23 } 24 25 // br.close(); 26 s.close(); 27 // ss.close(); 28 } 29 }
运行结果:
1 package cn.itcast_13; 2 3 import java.io.BufferedInputStream; 4 import java.io.BufferedOutputStream; 5 import java.io.FileInputStream; 6 import java.io.IOException; 7 import java.io.InputStream; 8 import java.net.Socket; 9 10 public class UploadClient { 11 public static void main(String[] args) throws IOException { 12 // 创建客户端Socket对象 13 Socket s = new Socket("192.168.12.92", 19191); 14 15 // 封装图片文件 16 BufferedInputStream bis = new BufferedInputStream(new FileInputStream( 17 "林青霞.jpg")); 18 // 封装通道内的流 19 BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream()); 20 21 byte[] bys = new byte[1024]; 22 int len = 0; 23 while ((len = bis.read(bys)) != -1) { 24 bos.write(bys, 0, len); 25 bos.flush(); 26 } 27 28 s.shutdownOutput(); 29 30 // 读取反馈 31 InputStream is = s.getInputStream(); 32 byte[] bys2 = new byte[1024]; 33 int len2 = is.read(bys2); 34 String client = new String(bys2, 0, len2); 35 System.out.println(client); 36 37 // 释放资源 38 bis.close(); 39 s.close(); 40 } 41 }
服务器端:
1 package cn.itcast_13; 2 3 import java.io.BufferedInputStream; 4 import java.io.BufferedOutputStream; 5 import java.io.FileOutputStream; 6 import java.io.IOException; 7 import java.io.OutputStream; 8 import java.net.ServerSocket; 9 import java.net.Socket; 10 11 public class UploadServer { 12 public static void main(String[] args) throws IOException { 13 // 创建服务器Socket对象 14 ServerSocket ss = new ServerSocket(19191); 15 16 // 监听客户端连接 17 Socket s = ss.accept(); 18 19 // 封装通道内流 20 BufferedInputStream bis = new BufferedInputStream(s.getInputStream()); 21 // 封装图片文件 22 BufferedOutputStream bos = new BufferedOutputStream( 23 new FileOutputStream("mn.jpg")); 24 25 byte[] bys = new byte[1024]; 26 int len = 0; 27 while ((len = bis.read(bys)) != -1) { 28 bos.write(bys, 0, len); 29 bos.flush(); 30 } 31 32 // 给一个反馈 33 OutputStream os = s.getOutputStream(); 34 os.write("图片上传成功".getBytes()); 35 36 bos.close(); 37 s.close(); 38 } 39 }
运行结果:
5、TCP传输容易出现的问题
(2) 通过例程分析:
因为read方法或者readLine方法是阻塞式。
(3) 解决办法:
自定义结束标记
使用shutdownInput,shutdownOutput方法。
六、客户端和服务器端原理
1、常见的客户端、服务器端
最常见的服务端:服务器,Tomcat。
2、常见网络结构
3、URL&URLConnection
URI:统一资源标示符。
URL:统一资源定位符,也就是说根据URL能够定位到网络上的某个资源,它是指向互联网“资源”的指针。
每个URL都是URI,但不一定每个URI都是URL。这是因为URI还包括一个子类,即统一资源名称
(URN),它命名资源但不指定如何定位资源。
转载于:https://www.cnblogs.com/AllenIverson/p/4768901.html