达内javaSE_day14学习笔记 —— 网络编程、模拟会话聊天室
程序员文章站
2022-05-25 21:16:40
...
javaSE_day14
1. 网络编程概述
1.1 计算机网络
将独立的,分散的计算机系统(手机,电脑)通过线路,通信设备(路由器,交换机)连接起来,由软件来实在资源共享,信息传递的系统。
1.2 网络模型
- OSI开放式系统互联。国际标准组织制定了OS七层网络模型(Open System Interconnection)模型
-
OSI七层网络模型
物理层、数据链路层、网络层、传输层、会话层、表示层、应用层
1.3 协议
- 事先规定好的通信规则
-
协议分类:
- 公有:IP、HTTP、UDP
- 私有: JDBC连接数据库的总协议
网络层:IP
传输层:UDP、TCP
应用层:FTP(上传下载(响应成功后不断开))、HTTP(宣传性网站(响应成功后断开))、HTTPS
1.4 IP地址
- IP地址:标识网络上的唯一一台计算机
- IP地址分为两个版本:IPv4(32位二进制)、IPv6(128位二进制)
1.5 端口
- 范围:0-65535
- (0-1024)是预留的端口号,已经被某些服务器占用
1.6域名解析
解析成IP地址
localhost(www.163.com) --> 127.0.0.1(72.1.1.1)
2. Java中的网络编程
2.1 UDP通信——写信
- 不需要创建连接
- 通过发送数据包通信 每个数据包最大64kb
- 不可靠的传输机制
- 传输速度快
- 追求速度快,可靠性要求不高的场景下 — 视频聊天
2.2 TCP通信——打电话
- 需要先创建连接。并且在创建连接的过程中,需要经过三次握手
- 底层通过 流 发送数据,数据大小没有限制
- 可靠的传输机制 – 丢包重发 包的顺序的保障
- 传输速度相对较慢
- 对于速度要求不太高,但是对可靠性要求比较高的场景下 - 文件上传 下载
eg:
要先启动接收端,再启动发送端
因为TCP在通信的过程中是需要创建连接的,
- 连接的发起者称为客户端;
- 监听端口等待被连接的一端称为服务端
服务端:
客户端:
案例:实现文件上传服务器
/**
* 实现上传功能
*/
public class DemoUploadServer {
public static void main(String[] args) throws IOException{
//1.创建套接字对象
ServerSocket serverSocket = new ServerSocket(4444);
Socket socket = serverSocket.accept();
//2.获取输入流对象,解析数据
InputStream inputStream = socket.getInputStream();
byte[] b = new byte[1];
String str = "";
while(!str.endsWith("\r\n")) {
inputStream.read(b);
str += new String(b);
}
//str="11\r\n";
int fileNameLen = Integer.parseInt(str.substring(0,str.length()-2)); //[0,2)
byte[] fileNameArr = new byte[fileNameLen];
inputStream.read(fileNameArr);
//文件名
String fileName = new String(fileNameArr);
byte[] b2 = new byte[1];
String str2 = "";
while(!str2.endsWith("\r\n")) {
inputStream.read(b2);
str2 += new String(b2);
}
int fileLen = Integer.parseInt(str2.substring(0,str2.length()-2));
byte[] fileArr = new byte[fileLen];
inputStream.read(fileArr);
//3.创建文件的输出流,把数据文件的数据(byte),写到upload文件夹下,文件夹名为原数据文件的名字
FileOutputStream fileOut = new FileOutputStream("upload/"+fileName);
fileOut.write(fileArr);
fileOut.close();
//4.使用输出流响应客户端的请求“上传成功!”
OutputStream out = socket.getOutputStream();
PrintWriter pWriter = new PrintWriter(out);//可以放字符流和字节流
pWriter.println("上传成功!");//ln换行表示输入输出流结束
pWriter.flush();//把没满的数据从缓冲区中推出来
//5.关闭流,关闭套接字对象
pWriter.close();
socket.close();
serverSocket.close();
}
}
/**
* 实现上传功能
*/
public class DemoUploadClient {
public static void main(String[] args) throws IOException {
//1.创建套接字对象
Socket socket = new Socket("127.0.0.1",4444);
//2.使用输出流输入数据文件内容
OutputStream outputStream = socket.getOutputStream();
//11 表示数据文件的文件名的长度(为了不浪费内存,也防止丢了数据); \r回车 \n换行 ; read_v1.txt表示传递给服务器的文件名 ; 100表示文件长度; 代码修正...表示文件内容
//[11\r\nread_v1.txt100\r\n代码修正...]
File file = new File("read_v1.txt");
//当前文件名长度
outputStream.write((file.getName().getBytes().length+"\r\n").getBytes());
//文件名
outputStream.write(file.getName().getBytes());
//文件长度
outputStream.write((file.length()+"\r\n").getBytes());
//写文件内容
FileInputStream fileIn = new FileInputStream(file);
byte[] buff = new byte[(int) file.length()];
fileIn.read(buff);
fileIn.close();
outputStream.write(buff);
//5.接收服务器的响应
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));//字节流转换为字符流
String msg = bufferedReader.readLine();
System.out.println(msg);
//6.close()
outputStream.close();
inputStream.close();
bufferedReader.close();
socket.close();
}
}
练习:模拟会话聊天室
v1:
代码修正
1.定义成员变量套接字
2.在构造方法中初始化
3.start方法处理读写
4.main方法创建对象,调用start方法
客户端:
public class Client {
private Socket socket;
public Client(){
try {
socket = new Socket("localhost",5555);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void start() throws IOException {
//获取输出流,写信息
OutputStream os = socket.getOutputStream();
PrintWriter pw = new PrintWriter(os);
pw.println("啦啦啦");
pw.flush();
//获取输入流,读信息
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String msg = br.readLine();
System.out.println(msg);
//关闭流,关闭套接字
br.close();
socket.close();
}
public static void main(String[] args) throws IOException {
Client client = new Client();
client.start();
}
}
服务端:
public class Server {
ServerSocket serverSocket;
Socket socket;
public Server() throws IOException {
serverSocket = new ServerSocket(5555);
socket = serverSocket.accept();
}
public void Start() throws IOException {
//获取输入流对象,读客户端的数据
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String msg = br.readLine();
System.out.println(msg);
//处理后的结果通过输出流,写出去
OutputStream os = socket.getOutputStream();
PrintWriter pw = new PrintWriter(os);
pw.println(msg);
pw.flush();
//关闭流,关闭套接字对象
br.close();
pw.close();
socket.close();
serverSocket.close();
}
public static void main(String[] args) throws IOException {
Server server = new Server();
server.Start();
}
}
v2:
控制台一对一会话
在客户端实现接收控制台输入
在v1的基础上,将客户端的写信息模块改进为控制台输入。
//客户端
//获取输出流,写信息
OutputStream os = socket.getOutputStream();
PrintWriter pw = new PrintWriter(os);
Scanner scanner = new Scanner(System.in);
System.out.println("input:");
String str = scanner.next();
pw.println(str);
pw.flush();
v3:
一个客户端和服务器多次会话
客户端使用while循环输入
服务器端使用while循环接收数据
在v2的基础上,将服务端中的start() 处理读写的方法改进到while循环中。
//服务端
public void Start() throws IOException {
Socket socket = serverSocket.accept();
OutputStream os = null;
InputStream is = null;
PrintWriter pw = null;
BufferedReader br = null;
try {
while(true) {
//获取输入流对象,读客户端的数据
is = socket.getInputStream();
br = new BufferedReader(new InputStreamReader(is));
String msg = br.readLine();
System.out.println(msg);
msg+="好的呢";
//处理后的结果通过输出流,写出去
os = socket.getOutputStream();
pw = new PrintWriter(os);
pw.println(msg);
pw.flush();
}
}catch(IOException e){
e.printStackTrace();
}finally {
//关闭流,关闭套接字对象
br.close();
pw.close();
socket.close();
serverSocket.close();
}
}
上一篇: riverplot绘制桑基图
下一篇: 桑基图-R