网络编程三要素
设备在网络中的地址
应用程序在设备中的唯一标识
数据在网络中传输的规则,常见的协议由UDP、http、HTTPS。ftp
TCP协议是传输层上的协议,保证数据**有序,可靠的,点对点,一对一 **的传输
TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个==Socket==对象
通信之前要保证连接已经建立
通过Socket产生IO流来进行网络通信
① 创建客户端的Socket对象(Socket)与指定服务器连接
Socket (String host , int port)
② 获取输出流,写数据
OutputStream getOutputStream()
③ 释放资源
void close()
// 建立与服务器的连接通道
Socket client = new Socket("192.168.254.175", 7999)) {
// 从连接通道获取字节输出流
OutputStream os = client.getOutputStream();
InputStream in = client.getInputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
BufferedReader br = new BufferedReader(new InputStreamReader(in));
bw.write("Hi");
// 换行表明本行已经读完
bw.newLine();
bw.flush();
System.out.println("服务器说:" + br.readLine()
① 创建服务器的Socket对象(ServerSocket)
ServerSocket (int port)
② 监听客户端连接,返回一个Socket对象,即客户端对象
Socket accept()
③ 获取输入流,读数据,并把数据显示在控制台
InputStream getInputStream()
④ 释放资源
void close()
// 创建服务器对象
ServerSocket server = new ServerSocket(7999)) {
// 让服务器处于等待状态(阻塞),若连接成功,则返回一个客户端连接对象,表示通道建立成功
Socket client = server.accept();
System.out.println("有新的客户端连接.....");
// getInetAddress()获取客户端的IP地址
System.out.println("客户端IP地址" + client.getInetAddress());
// 从通道内获取字节输入流对象
InputStream in = client.getInputStream();
// 从通道内获取字节输出流对象
OutputStream os=client.getOutputStream();
try(BufferedReader br = new BufferedReader(new InputStreamReader(in));
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(os))){
System.out.println("客户端说:"+br.readLine());
bw.write("收到,Over!");
bw.newLine();
bw.flush();
}
和TCP编程相比,UDP编程更加简单,因为UDP编程不需要创建连接
DatagramSocket ds = new DatagramSocket(6666); // 监听指定端口
while (true) { // 无限循环
// 数据缓冲区:
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
ds.receive(packet); // 收取一个UDP数据包
// 收取到的数据存储在buffer中,由packet.getOffset(), packet.getLength()指定起始位置和长度
// 将其按UTF-8编码转换为String:
String s = new String(packet.getData(), packet.getOffset(), packet.getLength(), StandardCharsets.UTF_8);
// 发送数据:
byte[] data = "ACK".getBytes(StandardCharsets.UTF_8);
packet.setData(data);
ds.send(packet);
}
DatagramSocket ds = new DatagramSocket();
ds.setSoTimeout(1000);
ds.connect(InetAddress.getByName("localhost"), 6666); // 连接指定服务器和端口
// 发送:
byte[] data = "Hello".getBytes();
DatagramPacket packet = new DatagramPacket(data, data.length);
ds.send(packet);
// 接收:
byte[] buffer = new byte[1024];
packet = new DatagramPacket(buffer, buffer.length);
ds.receive(packet);
String resp = new String(packet.getData(), packet.getOffset(), packet.getLength());
ds.disconnect();
byte[] data = "ACK".getBytes(StandardCharsets.UTF_8);
packet.setData(data);
ds.send(packet);
}
try {
// 创建URL对象:代表一个网址(统一资源定位符)
URL url = new URL("https://www.163.com/");
// 发起请求
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setRequestMethod("GET"); // 请求方式
connection.setConnectTimeout(3000);// 超时时间
connection.setRequestProperty("Accept",
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7");
connection.setRequestProperty("User-Agent",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36");
connection.connect(); // 发起请求
// 处理响应
// 读取来自服务器的响应内容
StringBuilder response = new StringBuilder(8192);
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8));) {
String line = null;
while ((line = reader.readLine()) != null) {
response.append(line);
}
}
// json开源库:解析HTML格式的工具
// 加载整个html网页的内容
Document htmlDocument = Jsoup.parse(response.toString());
// 查找
// 每一个Elements对象代表一个div对象
Elements elements = htmlDocument.select("div");
for (Element div : elements) {
Element p = div.firstElementChild();
// 获取标签之间的文本内容
String title = p.text();
System.out.println(title);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
四、Java Email
学习Java发送邮件,必然会涉及到的一个术语就是SMTP,而且在邮箱中设置SMTP的时候我们还会看到另外两个术语:POP3和IMAP
简单的说,这三个都是邮件收发相关的三种协议。
- SMTP:全称是“Simple Mail Transfer Protocol”,简单邮件传输协议,它是一组用于从源地址到目的地址传输邮件的规范,通过它来控制邮件的中转方式。SMTP 协议属于 TCP/IP 协议簇,它帮助每台计算机在发送或中转信件时找到下一个目的地。用于发送电子邮件的传输协议;
- POP3:全称是"Post Office Protocol 3",是邮局协议的第3个版本,它规定怎样将个人计算机连接到Internet的邮件服务器和下载电子邮件的电子协议。用于接收电子邮件的标准协议;
- IMAP:全称是"Internet Mail Access Protocol",即交互式邮件存取协议,它是跟POP3类似邮件访问标准协议之一。不同的是,开启了IMAP后,您在电子邮件客户端收取的邮件仍然保留在服务器上,同时在客户端上的操作都会反馈到服务器上,如:删除邮件,标记已读等,服务器上的邮件也会做相应的动作,是POP3的替代协议。
JavaMail是Oracle官方提供的一组API库,并没有包含在标准的JDK中,使用时需要我们自己导入架包
一般分为如下步骤
- 邮件服务器主机
- 传输协议SMTP
- 邮箱认证授权
- 发件人地址
- 收件人地址
- 收件人邮箱
- 邮件主题
- 邮件内容
1.创建邮件服务器主机
Properties props = new Properties();// 创建Properties对象,相当于SMTP服务器对象
props.put("mail.smtp.host", "smtp.163.com"); // SMTP主机名
props.put("mail.smtp.port", "25"); // 主机端口号
props.put("mail.smtp.auth", "true"); // 是否需要用户认证
props.put("mail.smtp.startls.enable", "true"); // 启用TLS加密
2.邮箱认证授权
// 参数1:服务器连接参数
// 参数2:账号和密码的授权认证对象
Session session = Session.getInstance(props, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(userName, password);
}
});
3.发送邮件
- 发送邮件时需要创建一个Message对象
- 需要设置发送方的地址
- 设置接受方的地址
- 设置邮件主题
- 设置邮件正文
- 最后发送
Message message=new Message(session);//发送邮件时需要创建一个Message对象
message.setFrom(new InternetAddress("[email protected]")); // 发件方地址
message.setRecipient(RecipientType.TO, new InternetAddress("[email protected]"));// 收件方地址
message.setRecipients(RecipientType.CC, new InternetAddress[] { new InternetAddress("[email protected]"),
new InternetAddress("[email protected]") });// 群发(抄送)
message.setSubject("测试文件"); // 设置邮件标题
Transport.send(message);// 发送邮件
说明
- RecipientType.TO —> 单发,发送方为一个
- RecipientType.CC ----> 群发(抄送),发送方为多个
4.发送带正文和附件的邮件
- 设置正文部分
BodyPart textPart = new MimeBodyPart();
textPart.setContent("用测试文件", "text/html;charset=utf-8");
如果正文中带有html标签的字段,需要在设置正文内容时加上“text/html;charset=utf-8”,表示该文本是超文本格式,并使用utf-8进行编码
- 设置附件内容
BodyPart filePart = new MimeBodyPart();
filePart.setDataHandler(new DataHandler(
new ByteArrayDataSource(
Files.readAllBytes(Paths.get("E:\\APESOURCE\\评论页面\\img\\bj.jpg")), "application/octet-stream")));
注意:
添加附件时,不能直接使用message.setText() 方法,而是需要创建一个Multipart对象
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(textPart);
multipart.addBodyPart(filePart);
- 将组装完成的multipart对象放到message中
message.setContent(multipart);
- 完成这些操作后即可发送
Transport.send(message);
5发送内嵌图片的HTML文件
Multipart multipart = new MimeMultipart();
// 正文部分
BodyPart textPart = new MimeBodyPart();
StringBuffer contentPart = new StringBuffer();
contentPart.append("用测试文件");
contentPart.append("");
textPart.setContent(contentPart.toString(), "text/html;charset=utf-8");
// 附件部分
BodyPart imagePart = new MimeBodyPart();
// 设置文件类型
imagePart.setDataHandler(new DataHandler(
new ByteArrayDataSource(
Files.readAllBytes(Paths.get("E:\\APESOURCE\\评论页面\\img\\bj.jpg")),
"application/octet-stream")));
// 设置当前图片为内嵌图片
imagePart.setHeader("Content-ID", "pinglun"); // 图片的内容ID
try {
// 1.创建session会话
Session session=mailUtil.createSession();
// 2.创建邮件对象
MimeMessage message = new MimeMessage(session);
message.setSubject("这是一封表白信"); // 设置邮件标题
message.setText("喜欢你好久了,只因你太美"); // 设置邮件正文
message.setFrom(new InternetAddress("[email protected]")); // 发件账号 message.setRecipient(RecipientType.TO, new InternetAddress("[email protected]")); // 收件账号
// 3.发送
Transport.send(message);
}catch (Exception e) {
}
五、FTP协议
1.什么是FTP协议
FTP是一种可以用来在网络上传输文件的协议。它分为客户端和服务器端,通常用于从客户端把文件传输到服务器端或者从服务器端下载文件到客户端。FTP协议带有外传输控制信息的功能,可以使用户对传输进行控制。主要的工作流程是:先建立控制连接,认证用户身份,然后建立数据连接进行文件传输。FTP的进程和属进程各自有各自的作用,主进程负责交互,属进程负责具体的数据传输。
2、基于FTP协议的上传与下载文件
1、打开FTP服务器
2、创建访问FTP服务器的客户端
FTPClient ftpClient = new FTPClient();
3、通过客户端访问FTP服务器并且验证用户名密码
用户名和密码均正确才能正常访问FTP服务器
// 连接FTP服务器并验证用户名密码
ftpClient.connect("192.168.180.1", 21);
ftpClient.login("coco", "123456");
4、通过客户端访问服务器当前目录中的所有文件
SimpleDateFormat fmt=new SimpleDateFormat("yyyy年MM月dd日"); // 日期格式化显示
// 通过客户端访问服务器当前目录中的所有文件
FTPFile[] listFiles = ftpClient.listFiles();
for (FTPFile ftpFile : listFiles) {
System.out.println("文件名称" + ftpFile.getName());
Date createData = ftpFile.getTimestamp().getTime();
System.out.println("创建时间" + fmt.format(createData));
System.out.println("文件大小" + ftpFile.getSize()+"字节");
}
5.如果文件名称中包含中文乱码,则需要加入
String fileName=ftpFile.getName();
fileName=new String(fileName.getBytes(“iso-8859-1”),“gb2312”);
即
SimpleDateFormat fmt=new SimpleDateFormat("yyyy年MM月dd日"); // 日期格式化显示
// 通过客户端访问服务器当前目录中的所有文件
FTPFile[] listFiles = ftpClient.listFiles();
for (FTPFile ftpFile : listFiles) {
String fileName=ftpFile.getName();
// 处理中文乱码
fileName=new String(fileName.getBytes("iso-8859-1"),"gb2312");
System.out.println("文件名称" + fileName);
Date createData = ftpFile.getTimestamp().getTime();
System.out.println("创建时间" + fmt.format(createData));
System.out.println("文件大小" + ftpFile.getSize()+"字节");
}
6、访问服务器中指定目录中的内容
加入一个判定条件即可
boolean isChanged = ftpClient.changeWorkingDirectory("111");
// 获取当前目录中的所有文件
if(isChanged) {
SimpleDateFormat fmt=new SimpleDateFormat("yyyy年MM月dd日"); // 日期格式化显示
FTPFile[] listFiles = ftpClient.listFiles();
for (FTPFile ftpFile : listFiles) {
String fileName=ftpFile.getName();
fileName=new String(fileName.getBytes("iso-8859-1"),"gb2312");
System.out.println("文件名称" + fileName);
Date createData = ftpFile.getTimestamp().getTime();
System.out.println("创建时间" + fmt.format(createData));
System.out.println("文件大小" + ftpFile.getSize()+"kb");
}
}else {
// 如果指定目录不存在,则创建
ftpClient.makeDirectory("111");
}
7、文件上传至FTP服务器的指定目录
FTPClient ftpClient = new FTPClient();
try (FileInputStream in = new FileInputStream("E:\\APESOURCE\\image\\day08\\2.jpg")) {
// 1.连接FTP服务器并检验用户名密码
ftpClient.connect("192.168.254.175", 21);
ftpClient.login("coco", "123456");
// 2.切换至个目录
boolean isChange = ftpClient.changeWorkingDirectory("oo");
if (!isChange) {
// 创建目录
ftpClient.makeDirectory("oo");
// 切换个人目录
ftpClient.changeWorkingDirectory("oo");
}
// 文件上传
// 设置文件的类型
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
// 存文件至FTP服务器
// 参数1:FTP文件的保存名称
// 参数2:本地文件输入流
boolean isStore = ftpClient.storeFile(System.currentTimeMillis() + ".jpg", in);
System.out.println("文件上传成功" + isStore);
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
8.从FTP服务器下载指定文件
FTPClient ftpClient=new FTPClient();
try(FileOutputStream out=new FileOutputStream("E:\\APESOURCE\\image"+System.currentTimeMillis()+".jpg")){
ftpClient.connect("192.168.254.175",21);
ftpClient.login("coco", "123456");
// 切换至个人目录
boolean isChange=ftpClient.changeWorkingDirectory("liubin");
// 下载指定文件
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);// 文件类型
boolean isRetrieve=ftpClient.retrieveFile("3.jpg", out);
System.out.println("下载成功?"+isRetrieve);
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
// 断开连接
ftpClient.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}