Hello friend, I'm |

Ritchie里其

园龄:2年6个月粉丝:4关注:7

网络编程

1. 简介

  • 网络:两台或多台设备通过一定物理设备连接起来构成了网络
  • 网络通信:两台设备之间通过网络实现数据传输
  • ip地址:用于唯一标识网络中的每台计算机
    • 查看ip地址:ipconfig
    • ip地址组成:网络地址+主机地址
    • IPv4和IPv6
    • IPv4表示:4个字节(32位)0~255
    • IPv6表示:16个字节(128位)

a. 域名:将ip地址映射成域名

b. 端口号:用于标识计算机上某个特定的网络程序065535,01024已被占用,smtp 25,http 80

TCP协议:

  • 三次握手
  • 可靠,速度慢

UDP协议(用户数据协议):

  • 大小限制64k
  • 速度快

2. InetAddress类

常用方法:

  • getLocalHost() 返回本地主机。
  • getByName() 在给定主机名的情况下确定主机的 IP 地址。
  • getHostAddress() 返回 IP 地址字符串(以文本表现形式)。
  • getHostName() 获取此 IP 地址的主机名。
package com.xxx;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class API_ {
public static void main(String[] args) throws UnknownHostException {
//返回本机的主机名/ip地址
InetAddress localHost = InetAddress.getLocalHost();
System.out.println(localHost);//DESKTOP-T5RI7XC/192.168.22.127
//根据指定主机名,获取InetAddress对象
InetAddress inetAddress = InetAddress.getByName("DESKTOP-T5RI7TC");
System.out.println(inetAddress);//DESKTOP-T5RI7XC/192.168.22.127
//根据域名返回InetAdddress对象
InetAddress inetAddress1 = InetAddress.getByName("www.baidu.com");
System.out.println(inetAddress1);//www.baidu.com/182.61.200.6
//根据InetAddress对象,获取对应的地址
String hostAddress = inetAddress.getHostAddress();
System.out.println(hostAddress);//192.168.22.127
//根据InetAddress对象,获取对应的主机名/域名
String hostName = inetAddress1.getHostName();
System.out.println(hostName);//www.baidu.com
}
}

3. Socket套接字

简介:

Socket网络应用程序被广泛使用,成为事实上的标准。

通信的两端都要有Socket,网络通信其实就是Socket通信。

客户端:发起通信的应用程序

服务端:等待通信请求

package com.xxx;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class SocketTcpServer {
public static void main(String[] args) throws IOException {
//思路
//1.在本机的9999端口监听, 等待连接
//如果本机有其他服务已经在监听9999,那么会失败
ServerSocket serverSocket = new ServerSocket (9999);
System.out.println("服务端在9999端口监听");
//2. 当没有客户端连接9999端口时,程序会阻塞,等待连接
//如果有客户端连接,则会返回Socket对象,程序继续往下执行
Socket socket = serverSocket.accept();
System.out.println("服务端socket=" + socket.getClass());
//3.通过socket.getInputStream() 读取客户端写入到数据通道的数据,显示
InputStream inputStream = socket.getInputStream();
// //4.通过IO流读取,字节流
// byte[] buffer = new byte[1024];
// int readLen = -1;
// while ((readLen = inputStream.read(buffer)) != -1) {
// System.out.println(new String(buffer,0,readLen));
// }
//通过IO读取,字符流
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String s = bufferedReader.readLine();
System.out.println(s);
//5.获取socket相关的输出流
OutputStream outputStream = socket.getOutputStream();
// outputStream.write("Hello Client".getBytes());
//使用字符输出流回复信息
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write("Hello Client 字符流");
bufferedWriter.newLine();//插入一个换行符,表示回复内容结束
bufferedWriter.flush();
System.out.println();
//6.关闭流和socket
// outputStream.close();
bufferedWriter.close();//关闭外层流就行
// inputStream.close();
bufferedReader.close();//关闭外层流就行
socket.close();
serverSocket.close();//服务socket也要关闭
}
}
package com.xxx;
import sun.reflect.generics.scope.Scope;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
class SocketTcpClient {
public static void main(String[] args) throws IOException {
//思路
//1.连接服务器(ip,端口号)
//连接本机的9999端口,连接成功时返回socket对象
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
System.out.println("客户端:" + socket.getClass());
//2.连接上后,生成Socket,通过getOutputStream得到和socket对象关联的输出流对象
OutputStream outputStream = socket.getOutputStream();
//3.通过输出流,写入数据到数据通道
// outputStream.write("Hello".getBytes());
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write("Hello Server 字符流");
bufferedWriter.newLine();//插入一个换行符,表示写入的内容结束。作用相当于设置结束标记,但是要求对方也要用readLine
bufferedWriter.flush();//使用字符流,需要手动刷新,否则数据不会写入到数据通道
// //设置结束标记
// socket.shutdownOutput();
//4.关闭流对象和socket
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String s = bufferedReader.readLine();
System.out.println(s);
//5.关闭流和socket
// inputStream.close();
bufferedReader.close();//关闭外层流就行
// outputStream.close();
bufferedWriter.close();//关闭外层流就行
socket.close();
System.out.println("客户端退出。。。");
}
}

3.1 案例:

上传文件

package com.xxx;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @author 王则钰 Wyzel
* @date 2022/10/30 12:39
* @Description
*/
public class TcpFileUploadServer {
public static void main(String[] args) throws Exception {
//1.服务端在本机监听7777端口
ServerSocket serverSocket = new ServerSocket(7777);
System.out.println("服务器在7777端口监听。。。");
//2.等待客户端连接
Socket socket = serverSocket.accept();
//8.读取客户端发送的数据
//通过Socket得到输入流
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
byte[] bytes = StreamUtils.streamToByteArray(bis);
//9.将得到的bytes数组,写入到指定路径,得到一个文件
String destFilePath = "src\\copy7.png";
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFilePath));
bos.write(bytes);
bos.close();
//11.向客户端回复收到
//通过Socket获取输出流
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bufferedWriter.write("服务端回复:收到图片");
bufferedWriter.flush();//把内容刷新到数据通道
socket.shutdownOutput();//设置写入结束标记
//10.关流
bufferedWriter.close();
bis.close();
socket.close();
serverSocket.close();
}
}
package com.xxx;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
public class TcpFileUploadClient {
public static void main(String[] args) throws Exception {
//3.客户端连接服务器,得到Socket对象
Socket socket = new Socket(InetAddress.getLocalHost(),7777);
//4.创建读取磁盘文件的输入流
String filePath = "D:\\a\\b\\7.png";
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));
//5.调用StreamUtils
//bytes就filPath是对应的字节数组
byte[] bytes = StreamUtils.streamToByteArray(bis);
//6.通过socket获取输出流,把bytes数据发送给服务端
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
bos.write(bytes);//将文件对应的字节数组内容,写入到数据通道
bis.close();
socket.shutdownOutput();//写入数据的结束标记
//12.接收从服务端回复的消息
InputStream inputStream = socket.getInputStream();
//使用StreamUtils的方法,将inputStream读取到的内容转为字符串
String s = StreamUtils.streamToString(inputStream);
System.out.println(s);
//7.关流
bos.close();
socket.close();
}
}
package com.xxx;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
public class StreamUtils {
/**
* 功能:将输入流转换成 byte[],即可以把文件的内容读取到byte[]
* @param is
* @return
* @throws Exception
*/
public static byte[] streamToByteArray(InputStream is) throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
//创建输出流对象
byte[] b = new byte[1024];//字节数组
int len;
while ((len = is.read(b)) != -1) {//循环读取
bos.write(b, 0, len);//吧读取到的数据,写入bos
}
byte[] array = bos.toByteArray();//把bos转换成字节数组
bos.close();
return array;
}
/**
* 功能:将 InputStream 转换成 String
* @param is
* @return
* @throws Exception
*/
public static String streamToString(InputStream is) throws Exception {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder builder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {//当读取到 null 时,就表示结束
builder.append(line + "\r\n");
}
return builder.toString();
}
}

4. TCP网络通信编程

netstat指令

  1. 在dos控制台输入命令:netstat -an可以查看当前主机网络情况,包括端口监听情况和网络连接情况
  2. netstat - an | more 可以分页显示
  3. Listening表示某个端口在监听

*客户端Socket连接成功后会有一个随机的端口号

5. UDP网络通信编程

  1. 类DatagramSocket和DatagramPacket[数据包/数据报]实现了基于UDP协议网络程序
  2. 数据包套接字DatagramSocket发送和接收,系统不保证能否送到目的地,也不能确定何时送达
  3. 数据报中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号
  4. UDP无需建立发送方和接收方的连接

UDP基本流程

  1. DatagramSocket和DatagramPacket
  2. 建立发送端,接收端
  3. 建立数据报DatagramPacket对象
  4. 调用DatagramSocket的发送、接收方法
  5. 关闭DatagramSocket
package com.xxx;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UdpReceiverA {
public static void main(String[] args) throws IOException, IOException {
//1. 创建一个 DatagramSocket 对象,准备在 9999 接收数据
DatagramSocket socket = new DatagramSocket(9999);
//2. 构建一个 DatagramPacket 对象,准备接收数据
// 在前面讲解 UDP 协议时,老师说过一个数据包最大 64k
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
//3. 调用 接收方法, 将通过网络传输的 DatagramPacket 对象
// 填充到 packet 对象
//提示: 当有数据包发送到 本机的 9999 端口时,就会接收到数据
// 如果没有数据包发送到 本机的 9999 端口, 就会阻塞等待.
System.out.println("接收端 A 等待接收数据..");
socket.receive(packet);
//4. 可以把 packet 进行拆包,取出数据,并显示.
int length = packet.getLength();//实际接收到的数据字节长度
byte[] data = packet.getData();//接收到数据
String s = new String(data, 0, length);
System.out.println(s);
//===回复信息给 B 端
// 将需要发送的数据,封装到 DatagramPacket 对象
data = "好的, 明天见".getBytes();
// 说明: 封装的 DatagramPacket 对象 data 内容字节数组 , data.length , 主机(IP) , 端口
packet = new DatagramPacket(data, data.length, InetAddress.getByName("192.168.1.117"), 9998);
socket.send(packet);//发送
// 5. 关闭资源
socket.close();
System.out.println("A 端退出...");
}
}
package com.xxx;
import java.io.IOException;
import java.net.*;
@SuppressWarnings({"all"})
public class UdpSenderB {
public static void main(String[] args) throws IOException {
//1.创建 DatagramSocket 对象,准备在 9998 端口 接收数据
DatagramSocket socket = new DatagramSocket(9998);
//2. 将需要发送的数据,封装到 DatagramPacket 对象
byte[] data = "hello 明天吃火锅~".getBytes(); //
// 说明: 封装的 DatagramPacket 对象 data 内容字节数组 , data.length , 主机(IP) , 端口
DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName("192.168.1.117"), 9999);
socket.send(packet);
//3.=== 接收从 A 端回复的信息
// (1) 构建一个 DatagramPacket 对象,准备接收数据
// 在前面讲解 UDP 协议时,老师说过一个数据包最大 64k
byte[] buf = new byte[1024];
packet = new DatagramPacket(buf, buf.length);
//(2) 调用 接收方法, 将通过网络传输的 DatagramPacket 对象
// 填充到 packet 对象
// 提示: 当有数据包发送到 本机的 9998 端口时,就会接收到数据
// 如果没有数据包发送到 本机的 9998 端口, 就会阻塞等待.
socket.receive(packet);
//(3) 可以把 packet 进行拆包,取出数据,并显示.
int length = packet.getLength();//实际接收到的数据字节长度
data = packet.getData();// 接收到数据
String s = new String(data, 0, length);
System.out.println(s);
//关闭资源
socket.close();
System.out.println("B 端退出");
}
}

本文作者:Ritchie里其

本文链接:https://www.cnblogs.com/wang-zeyu/p/16842105.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Ritchie里其  阅读(34)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
✨欢迎你~🍻
✨欢迎你~🍻
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 遥か Aimer
遥か - Aimer
00:00 / 00:00
An audio error has occurred.

作词 : aimerrhythm/田中ユウスケ

作曲 : 田中ユウスケ

编曲 : 玉井健二/百田留衣

海岸線の雨に ちらばった君の影

思い出が交差する 海辺の街

君はあの日のまま いまも夢を見てた

君はあの日のまま いまも夢を見てた

遥か記憶の空 2人照らす光

遥か記憶の空 2人照らす光

膝までの浅瀬で 見つけた星

君まで届くなんてさ ありえないような

浅い眠りの中で 深い夢から覚めて

浅い眠りの中で 深い夢から覚めて

裸足のまま駆けてく まばゆい星

君はあの日のまま どんな夢を見てた?

君はあの日のまま どんな夢を見てた?

遥か記憶の空 2人照らす光

遥か記憶の空 2人照らす光

いつまでもこうして 笑っててほしい

夜空に舞い上がる 幾千の花びら

でたらめな誓いで 生きてく日々

君から届くなんてさ ありえないような