day18【Socket网络编程】
反馈和复习
1.有没有时间一起复习
2.作业能不能多发几天
复习
1.缓冲流【重点】
a。作用:对普通类的增强(性能的增强)
b。BufferedWriter 特有方法: public void newLine();
c。BufferedReader 特有方法: public String readLine();
2.转换流【重点】
转换流可以在读写文件时指定编码
OutputStreamWriter 转换输出流 写数据时指定编码
InputStreamReader 转换输入流 读数据时指定编码
3.序列化流
操作对象的流
ObjectOutputStream 对象的输出流(序列化流),写对象
ObjectInputStream 对象的输入流(反序列化流),读对象
4.commons-io工具包
IOUtis 复制大的或者小的文件
FileUtils 复制文件也能复制文件夹
5.装饰者设计模式
作用: 在不该变原来类的代码,也不使用继承的基础上对某个类的功能进行增强
步骤:
a.同一个接口(被装饰类和装饰类实现同一个接口)
b.含有引用(装饰类内部必须具有被装饰类的引用)
c.对需要增强的方法进行增强
d.对不需要增强的方法调用被装饰类的同名方法
6.打印流
能方便的打印各种数据类型
PrintStream
print(各种类型)
println(各种类型)
今日内容
1.网络编程的概念(网络通信协议,IP地址,端口号)
2.TCP网络编程【重点】
3.综合案例(难度比较高,文件上传) 【理解】
第一章 网络编程入门【了解】
1.软件架构介绍
C/S架构: 客户端/服务器 比如:QQ,百度网盘,淘宝App
B/S结构: 浏览器/服务器 比如:网页QQ,网页淘宝
2.网络通信协议
-
什么是网络通信协议
网络: 互联网/局域网 通信: 数据传输 协议: 规则规范
-
TCP/IP协议
TCP协议: 传输控制协议 IP协议: 因特网协议
3.java中支持的常见协议
TCP协议: 传输控制协议
特点: 面向有连接(数据传输之前必须先建立连接,底层是通过"三次握手"建立连接)
优点: 保存数据是完整,安全的
缺点: 性能较低
UDP协议: 用户数据报协议
特点: 面向无连接(数据传输时不需要关系对方是否存在,甚至不需要关系对象是否开机)
缺点: 不能保证数据完整和不能保证安全的
优点: 性能较高
4.网络编程的三要素【重点】
1.网络通信协议
2.IP地址: 每台连接到互联网的计算机的唯一标识(就类似于人的身份证号,或者电话机的电话号码)
组成:由32位二进制组成 0110 0100 0100 0100 0100 0110 0100 0110
我们通常会搞成10进制: 192.168.120.250
3.端口号: 一台计算机上不同软件的标识
端口号一共有0-65535号,其中1024以下的端口被牛逼软件厂商占用!!(我们写软件时,用1024以上的)
5.计算机小知识
-
IP地址的分类
IPv4版本:由32位二进制组成,大概42亿种IP,面临枯竭 IPv6版本:由128位二进制组成,大概有可以给地球上每一粒沙子搞一个IP且不重复
-
IP地址的相关命令
ipconfig:查看本机IP ping 对方IP: 测试你和对象网络是否畅通/通畅
-
特殊的IP地址
127.0.0.1(localhost): 本机回环地址(相当于Java中this)
6.InetAddress类的基本使用
a.InetAddress类代表IP地址类
b.获取本地IP
InetAddress.getLocalHost();//获取主机(本机)的IP地址对象
c.获取其他机器的IP
InetAddress.getByName(域名/IP地址);//获取其他机器的IP地址对象
d.成员方法
String getHostName();获得主机名
String getHostAddress();获得IP地址字符串
public class InetAddressDemo {
public static void main(String[] args) throws UnknownHostException {
//1.获取本机的ip地址对象
InetAddress local = InetAddress.getLocalHost();
System.out.println(local);//DESKTOP-7CI8PTA/192.168.1.8
//2.获取其他机器的IP地址对象
InetAddress address = InetAddress.getByName("www.baidu.com");
System.out.println(address);//www.baidu.com/36.152.44.96
//3.成员方法
String hostName = address.getHostName();
String hostAddress = address.getHostAddress();
System.out.println(hostName);
System.out.println(hostAddress);
}
}
第二章 TCP通信【重点】
1.TCP通信分为客户端和服务器
客户端: 比如说我们的电脑
服务器端: 比如淘宝服务器
2.TCP中的两个重要的类【重点】
1.Socket类,代表客户端类(套接字)
2.ServerSocket类,代表服务器端类(服务器套接字)
3.Socket类的介绍和使用【重点】
-
构造方法
public Socket(String ip,int port);//服务器的IP地址,服务器的端口号 此构造非常牛逼!! 会根据传入的参数,自动去连接服务器 如果连接成功,那么对象正常创建 如果连接失败,那么直接抛出异常!!
-
常用方法
public OutputStream getOutputStream();//获取连接通道中输出流 public InputStream getInputStream();//获取连接通道中输入流 public void shutDownOutput();//关闭连接通道中的输出流 public void shutDownInput();//关闭连接通道中的输入流 public void close();//关闭客户端对象
4.ServerSocket类的介绍和使用【重点】
-
构造方法
public ServerSocket(int port);//指定服务器端使用的端口号
-
常用的成员方法
public Socket accept();//接收连接到服务器的那个Socket对象,如果暂时没有客户端,该方法会阻塞 public void close(); //关闭服务器端对象 注意: 服务器获取到客户端对象之后,也可以获取连接中两个流, 但是获取时是输入流还是输出流,相当于服务器而言了
5.简单的TCP通信实现(单向通信)【重点】
客户端给服务器发送信息,服务器不回!
public class SocketDemo {
public static void main(String[] args) throws IOException {
//1.创建Socket对象
Socket socket = new Socket("127.0.0.1",8888);
System.out.println("连接服务器成功...");
//2.获取输出流
OutputStream out = socket.getOutputStream();
//3.调用输出流的write方法
out.write("你好我是客户端!".getBytes());
System.out.println("数据发送成功...");
//4.释放资源
out.close();
socket.close();
System.out.println("客户端关闭了...");
}
}
public class ServerSocketDemo {
public static void main(String[] args) throws IOException {
//1.创建ServerSocket对象
ServerSocket server = new ServerSocket(8888);
System.out.println("服务器启动了...");
//2.接收连接到的客户端对象
Socket socket = server.accept(); //阻塞
System.out.println("有客户端来了...");
//3.获取输入流
InputStream in = socket.getInputStream();
//4.调用输入流的read方法
byte[] bs = new byte[1024];
int len = in.read(bs);
System.out.println("客户端说:"+new String(bs,0,len));
//5.释放资源
in.close();
socket.close();
server.close();
}
}
6.简单的TCP通信实现(双向通信)【重点】
客户端给服务器发信息,服务器接收到之后,给客户端回信息
public class SocketDemo {
public static void main(String[] args) throws IOException {
//客户端步骤:
//1.创建Socket对象
Socket socket = new Socket("127.0.0.1",9999);
System.out.println("连接成功...");
//2.获取输出流
OutputStream out = socket.getOutputStream();
//3.调用输出流的write方法
out.write("你好,我又来了...".getBytes());
System.out.println("发送成功...");
//==读取服务器回的信息==
//4.获取输入流
InputStream in = socket.getInputStream();
//5.调用输入流的read方法
byte[] bs = new byte[1024];
int len = in.read(bs);
System.out.println("服务器回复:" + new String(bs, 0, len));
//================
//6.释放资源
in.close();
out.close();
socket.close();
System.out.println("客户端关闭...");
}
}
public class ServerSocketDemo {
public static void main(String[] args) throws IOException {
//服务器的步骤
//1.创建ServerSocket对象
ServerSocket server = new ServerSocket(9999);
System.out.println("服务器启动...");
//2.接收连接到的客户端对象
Socket socket = server.accept();//阻塞
System.out.println("客户端来了...");
//3.获取输入流
InputStream in = socket.getInputStream();
//4.调用输入流的read方法
byte[] bs = new byte[1024];
int len = in.read(bs);
System.out.println("客户端说:" + new String(bs, 0, len));
//=======回信息========
//5.获取输出流
OutputStream out = socket.getOutputStream();
//6.调用输出流的write方法
out.write("您的信息我收到了,安息吧!".getBytes());
System.out.println("成功回复...");
//====================
//7.释放资源
out.close();
in.close();
socket.close();
server.close();
System.out.println("服务器关闭...");
}
}
第五章 综合案例:文件上传(较难,非重点)
1.文件上传案例分析(画图演示)
2.文件上传案例实现(代码演示)【增加点难度,多个客户端,多线程】
//客户端代码实现
public class SocketDemo {
public static void main(String[] args) throws IOException {
//文件上传客户端步骤:
//1.创建Socket
Socket socket = new Socket("127.0.0.1",9999);
System.out.println("连接成功...");
//2.获取输出流
OutputStream out = socket.getOutputStream();
//3.创建文件的输入流
FileInputStream fis = new FileInputStream("555.png");
//循环:一边读文件,一边发送
byte[] bs = new byte[1024];
int len = 0;
while ((len = fis.read(bs)) != -1) {
out.write(bs,0,len);
}
//添加一句代码,告知服务器文件发送完毕
socket.shutdownOutput();
System.out.println("文件上传完毕...");
//4.获取输入流
InputStream in = socket.getInputStream();
//5.读取服务器回复的信息
len = in.read(bs);
System.out.println("服务器回复:" + new String(bs, 0, len));
//6.释放资源
in.close();
fis.close();
out.close();
socket.close();
System.out.println("客户端关闭...");
}
}
//服务器代码实现
public class ServerSocketDemo {
public static void main(String[] args) throws IOException {
//文件上传服务器步骤:
//1.创建ServerSocket
ServerSocket server = new ServerSocket(9999);
System.out.println("服务器启动...");
//2.获取客户端
Socket socket = server.accept();
System.out.println("有客户端来了...");
//3.获取输入流
InputStream in = socket.getInputStream();
//4.创建文件的输出流
FileOutputStream fos = new FileOutputStream(System.currentTimeMillis()+".png");
//循环:一边读数据,一边写文件
byte[] bs = new byte[1024];
int len = 0;
while ((len = in.read(bs)) != -1) {
fos.write(bs, 0, len);
}
System.out.println("文件保存成功...");
//5.获取输出流
OutputStream out = socket.getOutputStream();
//6.给客户端回信息
out.write("您的图片我收到了,安息吧~~".getBytes());
System.out.println("消息回复成功...");
//7.释放资源
out.close();
fos.close();
in.close();
socket.close();
server.close();
System.out.println("服务器关闭...");
}
}
扩展_服务器多线程版本
public class ServerSocketMultiDemo {
public static void main(String[] args) throws IOException {
//文件上传服务器步骤:
//1.创建ServerSocket
ServerSocket server = new ServerSocket(9999);
System.out.println("服务器启动...");
//2.获取客户端
while (true) {
Socket socket = server.accept();
System.out.println("有客户端来了...");
//创建线程
new Thread(()->{
try {
//3.获取输入流
InputStream in = socket.getInputStream();
//4.创建文件的输出流
FileOutputStream fos = new FileOutputStream(System.currentTimeMillis() + ".png");
//循环:一边读数据,一边写文件
byte[] bs = new byte[1024];
int len = 0;
while ((len = in.read(bs)) != -1) {
fos.write(bs, 0, len);
}
System.out.println("文件保存成功...");
//5.获取输出流
OutputStream out = socket.getOutputStream();
//6.给客户端回信息
out.write("您的图片我收到了,安息吧~~".getBytes());
System.out.println("消息回复成功...");
//7.释放资源
out.close();
fos.close();
in.close();
socket.close();
} catch (IOException ie) {
ie.printStackTrace();
}
}).start();
}
//server.close();
//System.out.println("服务器关闭...");
}
}
3.模拟BS架构服务器【了解】
软件架构:CS和BS
4.扩展:模拟服务器扩展_图片显示问题【了解】
public class ServerSocketDemo {
public static void main(String[] args) throws IOException {
//1.创建服务器
ServerSocket server = new ServerSocket(12345);
System.out.println("服务器启动...");
//2.接收客户端
while (true) {
Socket socket = server.accept();
System.out.println("客户端来了..");
//3.获取输入流
InputStream in = socket.getInputStream();
//4.使用输入流的read方法,把浏览器发送过的数据读取出来
//我们现在只想读取,客户端要的那个文件
//a.只读第一行
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line = br.readLine();
//b.从中获取浏览器想要的那个文件名字
String[] splits = line.split(" ");
String fileName = splits[1].substring(1);
System.out.println("浏览器想要:" + fileName);
//5.把浏览器想要的文件,读取出来,发送给浏览器
FileInputStream fis = new FileInputStream(fileName);
OutputStream out = socket.getOutputStream();
byte[] bs = new byte[1024];
int len = 0;
out.write("HTTP/1.1 200 OK\r\n".getBytes());
out.write("Content-Type:text/html\r\n".getBytes());
out.write("\r\n".getBytes());
while ((len = fis.read(bs)) != -1) {
out.write(bs, 0, len);
}
//5.释放资源
in.close();
socket.close();
}
// server.close();
// System.out.println("服务器关闭..");
}
}
总结
能够说出TCP协议特点
TCP的特点: 面向有链接(先建立连接后才能数据传输)
UDP的特点: 面向无连接(只需要发送数据,不需要关心对象是否开机,是否存在)
能够说出TCP协议下两个常用类名称
Socket:客户端类(构造方法,成员方法)
ServerSocket:服务器类(构造方法和成员方法)
"能够编写TCP协议下字符串数据传输程序"【TCP的单、双向通信!!3遍!!】
能够理解TCP协议下文件上传案例
什么叫上传: 客户端把其硬盘中文件,通过网络发送到服务器端,并保存到服务器的硬盘中
上传过程: a.客户端读取本地文件 b.通过输出流发送给服务器
c.服务器读取输入流数据 d.保存到服务器的本地
能够理解TCP协议下BS案例
我们不需要自己编写客户端,使用浏览器当过客户端,去访问服务器
访问时: 127.0.0.1:8888