Java笔记(26):网络编程
Posted 花醉红尘
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java笔记(26):网络编程相关的知识,希望对你有一定的参考价值。
1、网络模型概述和图解
网络模型7层概述:
1.物理层:主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输,到达目的地后在转化为1、0,也就是我们常说的数模转换与模数转换)。这一层的数据叫做比特。
2. 数据链路层:主要将从物理层接收的数据进行MAC地址(网卡的地址)的封装与解封装。常把这一层的数据叫做帧。在这一层工作的设备是交换机,数据通过交换机来传输。
3. 网络层:主要将从下层接收到的数据进行IP地址(例192.168.0.1)的封装与解封装。在这一层工作的设备是路由器,常把这一层的数据叫做数据包。
4. 传输层:定义了一些传输数据的协议和端口号(WWW端口80等),如:TCP(传输控制协议,传输效率低,可靠性强,用于传输可靠性要求高,数据量大的数据),UDP(用户数据报协议,与TCP特性恰恰相反,用于传输可靠性要求不高,数据量小的数据,如QQ聊天数据就是通过这种方式传输的)。 主要是将从下层接收的数据进行分段和传输,到达目的地址后再进行重组。常常把这一层数据叫做段。
5.会话层:通过传输层(端口号:传输端口与接收端口)建立数据传输的通路。主要在你的系统之间发起会话或者接受会话请求(设备之间需要互相认识可以是IP也可以是MAC或者是主机名)
6.表示层:主要是进行对接收的数据进行解释、加密与解密、压缩与解压缩等(也就是把计算机能够识别的东西转换成人能够能识别的东西(如图片、声音等)。
7.应用层: 主要是一些终端的应用,比如说FTP(各种文件下载),WEB(IE浏览),QQ之类的(可以把它理解成我们在电脑屏幕上可以看到的东西.就是终端应用)。
2、网络基础
网络编程三要素:
A:IP地址
B:端口
C:协议
IP地址:
网络中计算机的唯一标识。
计算机只能识别二进制的数据,所以我们的IP地址应该是一个二进制的数据。
但是呢,我们配置的IP地址确不是二进制的,为什么呢?
IP:192.168.1.100
换算:11000000 10101000 00000001 01100100
假如真是:11000000 10101000 00000001 01100100的话。
我们如果每次再上课的时候要配置该IP地址,记忆起来就比较的麻烦。
所以,为了方便表示IP地址,我们就把IP地址的每一个字节上的数据换算成十进制,然后用.分开来表示:
"点分十进制"
IP地址的组成:网络号段+主机号段
A类:第一号段为网络号段+后三段的主机号段
一个网络号:256*256*256 = 16777216
B类:前二号段为网络号段+后二段的主机号段
一个网络号:256*256 = 65536
C类:前三号段为网络号段+后一段的主机号段
一个网络号:256
IP地址的分类:
A类 1.0.0.1---127.255.255.254 (1)10.X.X.X是私有地址(私有地址就是在互联网上不使用,而被用在局域网络中的地址) (2)127.X.X.X是保留地址,用做循环测试用的。
B类 128.0.0.1---191.255.255.254 172.16.0.0---172.31.255.255是私有地址。169.254.X.X是保留地址。
C类 192.0.0.1---223.255.255.254 192.168.X.X是私有地址
D类 224.0.0.1---239.255.255.254
E类 240.0.0.1---247.255.255.254
特殊的IP地址:
127.0.0.1 回环地址(表示本机)
x.x.x.255 广播地址
x.x.x.0 网络地址
端口号:
正在运行的程序的标识。
有效端口:0~65535,其中0~1024系统使用或保留端口。
协议:
通信的规则
UDP:
把数据打包
数据有限制
不建立连接
速度快
不可靠
TCP:
建立连接通道
数据无限制
速度慢
可靠
3、InetAddress类的概述和使用
1 package cn.itcast_01; 2 3 import java.net.InetAddress; 4 import java.net.UnknownHostException; 5 6 /* 7 * 如果一个类没有构造方法: 8 * A:成员全部是静态的(Math,Arrays,Collections) 9 * B:单例设计模式(Runtime) 10 * C:类中有静态方法返回该类的对象(InetAddress) 11 * class Demo { 12 * private Demo(){} 13 * 14 * public static Demo getXxx() { 15 * return new Demo(); 16 * } 17 * } 18 * 19 * 看InetAddress的成员方法: 20 * public static InetAddress getByName(String host):根据主机名或者IP地址的字符串表示得到IP地址对象 21 */ 22 public class InetAddressDemo { 23 public static void main(String[] args) throws UnknownHostException { 24 // public static InetAddress getByName(String host) 25 // InetAddress address = InetAddress.getByName("liuyi"); 26 // InetAddress address = InetAddress.getByName("192.168.12.92"); 27 InetAddress address = InetAddress.getByName("192.168.12.63"); 28 29 // 获取两个东西:主机名,IP地址 30 // public String getHostName() 31 String name = address.getHostName(); 32 // public String getHostAddress() 33 String ip = address.getHostAddress(); 34 System.out.println(name + "---" + ip); 35 } 36 }
Socket通信原理图解
4、UDP协议发送数据
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 }
5、UDP协议接收数据
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 }
6、UDP协议发送和接收数据代码优化
1 package cn.itcast_03; 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 // 创建一个包裹 18 byte[] bys = new byte[1024]; 19 DatagramPacket dp = new DatagramPacket(bys, bys.length); 20 21 // 接收数据 22 ds.receive(dp); 23 24 // 解析数据 25 String ip = dp.getAddress().getHostAddress(); 26 String s = new String(dp.getData(), 0, dp.getLength()); 27 System.out.println("from " + ip + " data is : " + s); 28 29 // 释放资源 30 ds.close(); 31 } 32 }
1 package cn.itcast_03; 2 3 import java.io.IOException; 4 import java.net.DatagramPacket; 5 import java.net.DatagramSocket; 6 import java.net.InetAddress; 7 8 public class SendDemo { 9 public static void main(String[] args) throws IOException { 10 // 创建发送端的Socket对象 11 DatagramSocket ds = new DatagramSocket(); 12 13 // 创建数据并打包 14 byte[] bys = "helloworld".getBytes(); 15 DatagramPacket dp = new DatagramPacket(bys, bys.length, 16 InetAddress.getByName("192.168.12.92"), 12345); 17 18 // 发送数据 19 ds.send(dp); 20 21 // 释放资源 22 ds.close(); 23 } 24 }
练习:发送端的数据来自于键盘录入案例
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 }
1 package cn.itcast_04; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 import java.net.DatagramPacket; 7 import java.net.DatagramSocket; 8 import java.net.InetAddress; 9 10 /* 11 * 数据来自于键盘录入 12 * 键盘录入数据要自己控制录入结束。 13 */ 14 public class SendDemo { 15 public static void main(String[] args) throws IOException { 16 // 创建发送端的Socket对象 17 DatagramSocket ds = new DatagramSocket(); 18 19 // 封装键盘录入数据 20 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 21 String line = null; 22 while ((line = br.readLine()) != null) { 23 if ("886".equals(line)) { 24 break; 25 } 26 27 // 创建数据并打包 28 byte[] bys = line.getBytes(); 29 // DatagramPacket dp = new DatagramPacket(bys, bys.length, 30 // InetAddress.getByName("192.168.12.92"), 12345); 31 DatagramPacket dp = new DatagramPacket(bys, bys.length, 32 InetAddress.getByName("192.168.12.255"), 12345); 33 34 // 发送数据 35 ds.send(dp); 36 } 37 38 // 释放资源 39 ds.close(); 40 } 41 }
7、多线程实现聊天室程序
1 package cn.itcast_05; 2 3 import java.io.IOException; 4 import java.net.DatagramSocket; 5 6 /* 7 * 通过多线程改进刚才的聊天程序,这样我就可以实现在一个窗口发送和接收数据了 8 */ 9 public class ChatRoom { 10 public static void main(String[] args) throws IOException { 11 DatagramSocket dsSend = new DatagramSocket(); 12 DatagramSocket dsReceive = new DatagramSocket(12306); 13 14 SendThread st = new SendThread(dsSend); 15 ReceiveThread rt = new ReceiveThread(dsReceive); 16 17 Thread t1 = new Thread(st); 18 Thread t2 = new Thread(rt); 19 20 t1.start(); 21 t2.start(); 22 } 23 }
1 package cn.itcast_05; 2 3 import java.io.IOException; 4 import java.net.DatagramPacket; 5 import java.net.DatagramSocket; 6 7 public class ReceiveThread implements Runnable { 8 private DatagramSocket ds; 9 10 public ReceiveThread(DatagramSocket ds) { 11 this.ds = ds; 12 } 13 14 @Override 15 public void run() { 16 try { 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 } catch (IOException e) { 31 e.printStackTrace(); 32 } 33 } 34 35 }
1 package cn.itcast_05; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 import java.net.DatagramPacket; 7 import java.net.DatagramSocket; 8 import java.net.InetAddress; 9 10 public class SendThread implements Runnable { 11 12 private DatagramSocket ds; 13 14 public SendThread(DatagramSocket ds) { 15 this.ds = ds; 16 } 17 18 @Override 19 public void run() { 20 try { 21 // 封装键盘录入数据 22 BufferedReader br = new BufferedReader(new InputStreamReader( 23 System.in)); 24 String line = null; 25 while ((line = br.readLine()) != null) { 26 if ("886".equals(line)) { 27 break; 28 } 29 30 // 创建数据并打包 31 byte[] bys = line.getBytes(); 32 // DatagramPacket dp = new DatagramPacket(bys, bys.length, 33 // InetAddress.getByName("192.168.12.92"), 12345); 34 DatagramPacket dp = new DatagramPacket(bys, bys.length, 35 InetAddress.getByName("192.168.12.255"), 12306); 36 37 // 发送数据 38 ds.send(dp); 39 } 40 41 // 释放资源 42 ds.close(); 43 } catch (IOException e) { 44 e.printStackTrace(); 45 } 46 } 47 48 }
8、TCP协议发送数据
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 { Java网络编程(读书笔记)[原创]java WEB学习笔记61:Struts2学习之路--通用标签 property,uri,param,set,push,if-else,itertor,sort,date,a标签等(代码片段