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 { 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 }
9、TCP协议接收数据
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 }
TCP协议发送和接收数据图解:
练习:服务器端给客户端一个反馈案例
1 package cn.itcast_07; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.io.OutputStream; 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(9999); 13 14 // 监听客户端的连接 15 Socket s = ss.accept(); // 阻塞 16 17 // 获取输入流 18 InputStream is = s.getInputStream(); 19 byte[] bys = new byte[1024]; 20 int len = is.read(bys); // 阻塞 21 String server = new String(bys, 0, len); 22 System.out.println("server:" + server); 23 24 // 获取输出流 25 OutputStream os = s.getOutputStream(); 26 os.write("数据已经收到".getBytes()); 27 28 // 释放资源 29 s.close(); 30 // ss.close(); 31 } 32 }
1 package cn.itcast_07; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.io.OutputStream; 6 import java.net.Socket; 7 8 public class ClientDemo { 9 public static void main(String[] args) throws IOException { 10 // 创建客户端Socket对象 11 Socket s = new Socket("192.168.12.92", 9999); 12 13 // 获取输出流 14 OutputStream os = s.getOutputStream(); 15 os.write("今天天气很好,适合睡觉".getBytes()); 16 17 // 获取输入流 18 InputStream is = s.getInputStream(); 19 byte[] bys = new byte[1024]; 20 int len = is.read(bys);// 阻塞 21 String client = new String(bys, 0, len); 22 System.out.println("client:" + client); 23 24 // 释放资源 25 s.close(); 26 } 27 }
练习:客户端键盘录入服务器控制台输出
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_09; 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", 23456); 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 if ("over".equals(line)) { 27 break; 28 } 29 30 bw.write(line); 31 bw.newLine(); 32 bw.flush(); 33 } 34 35 // bw.close(); 36 // br.close(); 37 s.close(); 38 } 39 }
1 package cn.itcast_09; 2 3 import java.io.BufferedReader; 4 import java.io.BufferedWriter; 5 import java.io.FileWriter; 6 import java.io.IOException; 7 import java.io.InputStreamReader; 8 import java.net.ServerSocket; 9 import java.net.Socket; 10 11 public class ServerDemo { 12 public static void main(String[] args) throws IOException { 13 // 创建服务器Socket对象 14 ServerSocket ss = new ServerSocket(23456); 15 16 // 监听客户端连接 17 Socket s = ss.accept(); 18 19 // 封装通道内的数据 20 BufferedReader br = new BufferedReader(new InputStreamReader( 21 s.getInputStream())); 22 // 封装文本文件 23 BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt")); 24 25 String line = null; 26 while ((line = br.readLine()) != null) { 27 bw.write(line); 28 bw.newLine(); 29 bw.flush(); 30 } 31 32 bw.close(); 33 // br.close(); 34 s.close(); 35 // ss.close(); 36 } 37 }
练习:客户端读取文本文件服务器控制台输出
1 package cn.itcast_10; 2 3 import java.io.BufferedReader; 4 import java.io.BufferedWriter; 5 import java.io.FileReader; 6 import java.io.IOException; 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", 34567); 17 18 // 封装文本文件 19 BufferedReader br = new BufferedReader(new FileReader( 20 "InetAddressDemo.java")); 21 // 封装通道内的流 22 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter( 23 s.getOutputStream())); 24 25 String line = null; 26 while ((line = br.readLine()) != null) { 27 bw.write(line); 28 bw.newLine(); 29 bw.flush(); 30 } 31 32 br.close(); 33 s.close(); 34 } 35 }
1 package cn.itcast_10; 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(34567); 13 14 // 监听客户端连接 15 Socket s = ss.accept(); 16 17 // 封装通道内的流 18 BufferedReader br = new BufferedReader(new InputStreamReader( 19 s.getInputStream())); 20 21 String line = null; 22 while ((line = br.readLine()) != null) { 23 System.out.println(line); 24 } 25 26 27 s.close(); 28 } 29 }
练习:TCP协议上传文本文件
1 package cn.itcast_11; 2 3 import java.io.BufferedReader; 4 import java.io.BufferedWriter; 5 import java.io.FileReader; 6 import java.io.IOException; 7 import java.io.OutputStreamWriter; 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", 11111); 14 15 // 封装文本文件 16 BufferedReader br = new BufferedReader(new FileReader( 17 "InetAddressDemo.java")); 18 // 封装通道内流 19 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter( 20 s.getOutputStream())); 21 22 String line = null; 23 while ((line = br.readLine()) != null) { 24 bw.write(line); 25 bw.newLine(); 26 bw.flush(); 27 } 28 29 // 释放资源 30 br.close(); 31 s.close(); 32 } 33 }
1 package cn.itcast_11; 2 3 import java.io.BufferedReader; 4 import java.io.BufferedWriter; 5 import java.io.FileWriter; 6 import java.io.IOException; 7 import java.io.InputStreamReader; 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(11111); 15 16 // 监听客户端连接 17 Socket s = ss.accept(); 18 19 // 封装通道内的流 20 BufferedReader br = new BufferedReader(new InputStreamReader( 21 s.getInputStream())); 22 // 封装文本文件 23 BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java")); 24 25 String line = null; 26 while ((line = br.readLine()) != null) { 27 bw.write(line); 28 bw.newLine(); 29 bw.flush(); 30 } 31 32 bw.close(); 33 s.close(); 34 } 35 }
练习:TCP上传文本文件并给出反馈
1 package cn.itcast_12; 2 3 import java.io.BufferedReader; 4 import java.io.BufferedWriter; 5 import java.io.FileReader; 6 import java.io.IOException; 7 import java.io.InputStreamReader; 8 import java.io.OutputStreamWriter; 9 import java.net.Socket; 10 11 /* 12 * 按照我们正常的思路加入反馈信息,结果却没反应。为什么呢? 13 * 读取文本文件是可以以null作为结束信息的,但是呢,通道内是不能这样结束信息的。 14 * 所以,服务器根本就不知道你结束了。而你还想服务器给你反馈。所以,就相互等待了。 15 * 16 * 如何解决呢? 17 * A:在多写一条数据,告诉服务器,读取到这条数据说明我就结束,你也结束吧。 18 * 这样做可以解决问题,但是不好。 19 * B:Socket对象提供了一种解决方案 20 * public void shutdownOutput() 21 */ 22 23 public class UploadClient { 24 public static void main(String[] args) throws IOException { 25 // 创建客户端Socket对象 26 Socket s = new Socket("192.168.12.92", 11111); 27 28 // 封装文本文件 29 BufferedReader br = new BufferedReader(new FileReader( 30 "InetAddressDemo.java")); 31 // 封装通道内流 32 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter( 33 s.getOutputStream())); 34 35 String line = null; 36 while ((line = br.readLine()) != null) { // 阻塞 37 bw.write(line); 38 bw.newLine(); 39 bw.flush(); 40 } 41 42 //自定义一个结束标记 43 // bw.write("over"); 44 // bw.newLine(); 45 // bw.flush(); 46 47 //Socket提供了一个终止,它会通知服务器你别等了,我没有数据过来了 48 s.shutdownOutput(); 49 50 // 接收反馈 51 BufferedReader brClient = new BufferedReader(new InputStreamReader( 52 s.getInputStream())); 53 String client = brClient.readLine(); // 阻塞 54 System.out.println(client); 55 56 // 释放资源 57 br.close(); 58 s.close(); 59 } 60 }
1 package cn.itcast_12; 2 3 import java.io.BufferedReader; 4 import java.io.BufferedWriter; 5 import java.io.FileWriter; 6 import java.io.IOException; 7 import java.io.InputStreamReader; 8 import java.io.OutputStreamWriter; 9 import java.net.ServerSocket; 10 import java.net.Socket; 11 12 public class UploadServer { 13 public static void main(String[] args) throws IOException { 14 // 创建服务器端的Socket对象 15 ServerSocket ss = new ServerSocket(11111); 16 17 // 监听客户端连接 18 Socket s = ss.accept();// 阻塞 19 20 // 封装通道内的流 21 BufferedReader br = new BufferedReader(new InputStreamReader( 22 s.getInputStream())); 23 // 封装文本文件 24 BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java")); 25 26 String line = null; 27 while ((line = br.readLine()) != null) { // 阻塞 28 // if("over".equals(line)){ 29 // break; 30 // } 31 bw.write(line); 32 bw.newLine(); 33 bw.flush(); 34 } 35 36 // 给出反馈 37 BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter( 38 s.getOutputStream())); 39 bwServer.write("文件上传成功"); 40 bwServer.newLine(); 41 bwServer.flush(); 42 43 // 释放资源 44 bw.close(); 45 s.close(); 46 } 47 }
练习:TCP协议上传图片并给出反馈
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 }
练习:多线程改进多个客户端上传文件案例
1 package cn.itcast_15; 2 3 import java.io.BufferedReader; 4 import java.io.BufferedWriter; 5 import java.io.FileReader; 6 import java.io.IOException; 7 import java.io.InputStreamReader; 8 import java.io.OutputStreamWriter; 9 import java.net.Socket; 10 11 public class UploadClient { 12 public static void main(String[] args) throws IOException { 13 // 创建客户端Socket对象 14 Socket s = new Socket("192.168.12.92", 11111); 15 16 // 封装文本文件 17 // BufferedReader br = new BufferedReader(new FileReader( 18 // "InetAddressDemo.java")); 19 BufferedReader br = new BufferedReader(new FileReader( 20 "ReceiveDemo.java")); 21 // 封装通道内流 22 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter( 23 s.getOutputStream())); 24 25 String line = null; 26 while ((line = br.readLine()) != null) { // 阻塞 27 bw.write(line); 28 bw.newLine(); 29 bw.flush(); 30 } 31 32 // Socket提供了一个终止,它会通知服务器你别等了,我没有数据过来了 33 s.shutdownOutput(); 34 35 // 接收反馈 36 BufferedReader brClient = new BufferedReader(new InputStreamReader( 37 s.getInputStream())); 38 String client = brClient.readLine(); // 阻塞 39 System.out.println(client); 40 41 // 释放资源 42 br.close(); 43 s.close(); 44 } 45 }
1 package cn.itcast_15; 2 3 import java.io.BufferedReader; 4 import java.io.BufferedWriter; 5 import java.io.FileWriter; 6 import java.io.IOException; 7 import java.io.InputStreamReader; 8 import java.io.OutputStreamWriter; 9 import java.net.Socket; 10 11 public class UserThread implements Runnable { 12 private Socket s; 13 14 public UserThread(Socket s) { 15 this.s = s; 16 } 17 18 @Override 19 public void run() { 20 try { 21 // 封装通道内的流 22 BufferedReader br = new BufferedReader(new InputStreamReader( 23 s.getInputStream())); 24 // 封装文本文件 25 // BufferedWriter bw = new BufferedWriter(new 26 // FileWriter("Copy.java")); 27 28 // 为了防止名称冲突 29 String newName = System.currentTimeMillis() + ".java"; 30 BufferedWriter bw = new BufferedWriter(new FileWriter(newName)); 31 32 String line = null; 33 while ((line = br.readLine()) != null) { // 阻塞 34 bw.write(line); 35 bw.newLine(); 36 bw.flush(); 37 } 38 39 // 给出反馈 40 BufferedWriter bwServer = new BufferedWriter( 41 new OutputStreamWriter(s.getOutputStream())); 42 bwServer.write("文件上传成功"); 43 bwServer.newLine(); 44 bwServer.flush(); 45 46 // 释放资源 47 bw.close(); 48 s.close(); 49 } catch (IOException e) { 50 e.printStackTrace(); 51 } 52 } 53 54 }
1 package cn.itcast_15; 2 3 import java.io.IOException; 4 import java.net.ServerSocket; 5 import java.net.Socket; 6 7 public class UploadServer { 8 public static void main(String[] args) throws IOException { 9 // 创建服务器Socket对象 10 ServerSocket ss = new ServerSocket(11111); 11 12 while (true) { 13 Socket s = ss.accept(); 14 new Thread(new UserThread(s)).start(); 15 } 16 } 17 }