文章目录
netstat 指令
- netstat - an 可以查看当前主机网络情况,包括端口监听情况和网络连接情况
- netstat - an | more 可以分页显示,光标显示后点回车下一页
- ctrl + c 退出指令
案例表示
TCP网络通讯不为人知的秘密
- 当客户端连接到服务端后,实际上客户端也是通过一个端口和服务端进行通讯的,这个端口是TCP/IP来分配的
UDP网络通信编程[了解]
基本介绍
- 类DatagramSocket 和 DatagramPacket 实现了基于UDP协议网络程序。
- UDP数据报通过数据报套接字 DatagramSocket 发送和接收,系统不保证UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达
- DatagramPacket 对象封装了UDP数据报,在数据中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号
- UDP协议中每个数据报都给出了完整的地址信息,因此无需建立发送方和接收方的连接
基本流程
- 核心的两个类/对象 DatagramSocket与DatagramPacket
- 建立发送端,接收端(没有服务端和客户端概念)
- 发送数据前,建立数据包/报 (DatagramPack对象)
- 调用DatagramSocket的发送,接收方法
- 关闭DatagramSocket
应用案例
- 编写一个接收端A,和一个发送端B
- 接收端A在9999端口等待接受数据(receive)
- 发送端B向接收端A 发送数据“hello,明天吃火锅~”
- 接收端A接收到 发送端B发送的数据,回复“好的,明天见”,再退出
- 发送端接收 回复的数据,再退出
接收端
package com.tao.udp;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
* Create By 刘鸿涛
* 2022/2/8 9:55
* UDP接收端
*/
public class UDPReceiverA {
public static void main(String[] args) throws IOException {
//1.创建一个 DatagramSocket 对象 准备在9999接收数据
DatagramSocket datagramSocket = new DatagramSocket(9999);
//2.构建一个DatagramPacket对象,准备接收数据
// 在前面学习UDP协议时,知道一个UDP数据包最大64k
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
//3.调用接收方法receive(),将通过网络传输的 DatagramPacket对象
//提示:当有数据包发送到 本机的9999端口时,就会阻塞等待
System.out.println("接收端A,9999端口, 等待接收数据....");
datagramSocket.receive(packet);
System.out.println("1");
//4.可以把packet 进行拆包,取出数据,并显示
int length = packet.getLength(); //实际接收到的数据字节长度
byte[] data = packet.getData(); //接收到数据
String s = new String(data, 0, length);
System.out.println(s);
data = "好的,明天见".getBytes();
//说明:封装的 DatagramPacket 对象 data 内容字节数组,data.length,主机(IP),端口
// InetAddress.getLocalHost() //获得主机ip
DatagramPacket datagramPacket = new DatagramPacket(data, data.length,
InetAddress.getLocalHost(), 9998);//这里的127.0.0.1指发送给本机
datagramSocket.send(datagramPacket);
//关闭流
datagramSocket.close();
System.out.println("===接收端已终止===");
}
}
发送端
package com.tao.udp;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
* Create By 刘鸿涛
* 2022/2/8 9:57
* 发送端B ====> 也可以接收数据
*/
public class UDPSenderB {
public static void main(String[] args)throws Exception {
//创建 DatagramSocket对象,准备接收数据
//
//因为是在本机举例接收端和发送端,所以这个端口号最好不要相同,因为会分不清谁是接收方,
// 谁是发送方,导致程序错乱,当然,如果是两台主机,那么就可以使用相同端口号,就比如
// 是两个楼层中两个相同id的门一样,虽然id相同,但并不是一个门
DatagramSocket datagramSocket = new DatagramSocket(9998);
//2.将需要发送的数据,封装到 DatagramPacket对象
byte[] data = "hello 明天吃火锅".getBytes();
//说明:封装的 DatagramPacket 对象 data 内容字节数组,data.length,主机(IP),端口
// InetAddress.getLocalHost() //获得主机ip
DatagramPacket datagramPacket = new DatagramPacket(data, data.length,
InetAddress.getLocalHost(), 9999);//这里的127.0.0.1指发送给本机
datagramSocket.send(datagramPacket);
byte[] buf = new byte[1024];
datagramPacket = new DatagramPacket(buf, buf.length);
datagramSocket.receive(datagramPacket);
int length = datagramPacket.getLength(); //实际接收到的数据字节长度
byte[] data2 = datagramPacket.getData(); //接收到数据
String s = new String(data2, 0, length);
System.out.println(s);
//关闭资源
datagramSocket.close();
System.out.println("===发送端已终止===");
}
}
网络编程练习(课堂作业巩固)
TCP交互传输字节流回复
- 使用字节流的方式,编写一个客户端程序和服务端程序
- 客户端发送“name”,服务器端接收到后,返回,“我是nova”,nova是你自己的名字
- 客户端发送“hobby”,服务器端接收到后,返回“编写java程序”
- 不是这样两个问题,回复“你说啥呢”
package com.tao.homework.homework01;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* Create By 刘鸿涛
* 2022/2/8 20:44
*/
public class Server {
public static void main(String[] args) throws IOException {
while(true) {
ServerSocket serverSocket = new ServerSocket(5000);
//监听
System.out.println("等待客户端连接连接");
Socket socket = serverSocket.accept();
System.out.println("正在接收数据...");
InputStream inputStream = socket.getInputStream(); //接收数据通道的数据
//IO读取
byte[] buf = new byte[1024];
int len = 0;
String s = "";
while ((len = inputStream.read(buf)) != -1) {
s = new String(buf, 0, len);
if (s.equals("name")) {
s = "我是涛涛";
} else if (s.equals("hobby")) {
s = "编写java程序";
} else {
s = "你说啥";
}
}
OutputStream outputStream = socket.getOutputStream();
outputStream.write(s.getBytes()); //写入s到数据通道
socket.shutdownOutput(); //结束语句,我说完了
System.out.println("正在传输数据到数据通道...");
//关闭流
socket.close();
inputStream.close();
serverSocket.close();
System.out.println("服务器端结束");
}
}
}
package com.tao.homework.homework01;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;
/**
* Create By 刘鸿涛
* 2022/2/8 20:48
*/
public class Client {
public static void main(String[] args) throws IOException, InterruptedException {
while(true) {
Socket socket = new Socket(InetAddress.getLocalHost(), 5000);
System.out.println("请输入问题");
Scanner sc = new Scanner(System.in);
String s = sc.next();
OutputStream outputStream = socket.getOutputStream();
outputStream.write(s.getBytes());
socket.shutdownOutput(); //结束语句,证明我说完了
InputStream inputStream = socket.getInputStream();
byte[] buf = new byte[1024];
int len = 0;
while ((len = inputStream.read(buf)) != -1) {
System.out.println(new String(buf, 0, len));
}
//关闭流
socket.close();
outputStream.close();
System.out.println("客户端结束");
}
}
}
UDP交互传输字节流回复
- 编写一个接收端A,和一个发送端B,使用UDP协议完成
- 接收端在8888端口等待接收数据(receive)
- 发送端向接收端发送数据“四大名著是哪些”
- 接收端接收到发送端发送的问题后,返回“四大名著是<<红楼梦>>…",否则返回what?
- 接收端和发送端程序退出
package com.tao.homework.homework02;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
* Create By 刘鸿涛
* 2022/2/8 9:55
* UDP接收端
*/
public class Homework02ReceiverA {
public static void main(String[] args) throws IOException {
//1.创建一个 DatagramSocket 对象 准备在9999接收数据
DatagramSocket datagramSocket = new DatagramSocket(9999);
//2.构建一个DatagramPacket对象,准备接收数据
// 在前面学习UDP协议时,知道一个UDP数据包最大64k
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
//3.调用接收方法receive(),将通过网络传输的 DatagramPacket对象
//提示:当有数据包发送到 本机的9999端口时,就会阻塞等待
System.out.println("接收端A,9999端口, 等待接收数据....");
datagramSocket.receive(packet);
//4.可以把packet 进行拆包,取出数据,并显示
int length = packet.getLength(); //实际接收到的数据字节长度
byte[] data = packet.getData(); //接收到数据
String s = new String(data, 0, length);
String answer = "";
if ("四大名著有哪些".equals(s) ){
answer = "四大名著 《红楼梦》《三国演义》《西游记》《水浒传》";
}else {
answer = "你说啥?";
}
// System.out.println(s);
data = answer.getBytes();
//说明:封装的 DatagramPacket 对象 data 内容字节数组,data.length,主机(IP),端口
// InetAddress.getLocalHost() //获得主机ip
DatagramPacket datagramPacket = new DatagramPacket(data, data.length,
InetAddress.getLocalHost(), 9998);//这里的127.0.0.1指发送给本机
datagramSocket.send(datagramPacket);
//关闭流
datagramSocket.close();
System.out.println("===接收端已终止===");
}
}
package com.tao.homework.homework02;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
/**
* Create By 刘鸿涛
* 2022/2/8 9:57
* 发送端B ====> 也可以接收数据
*/
public class Homework02SenderB {
public static void main(String[] args)throws Exception {
//创建 DatagramSocket对象,准备接收数据
//
//因为是在本机举例接收端和发送端,所以这个端口号最好不要相同,因为会分不清谁是接收方,
// 谁是发送方,导致程序错乱,当然,如果是两台主机,那么就可以使用相同端口号,就比如
// 是两个楼层中两个相同id的门一样,虽然id相同,但并不是一个门
DatagramSocket datagramSocket = new DatagramSocket(9998);
//2.将需要发送的数据,封装到 DatagramPacket对象
//把字符a包装送到数据通道
System.out.println("请输入查询内容...");
Scanner scanner = new Scanner(System.in);
String a = scanner.next();
byte[] data = a.getBytes();
//说明:封装的 DatagramPacket 对象 data 内容字节数组,data.length,主机(IP),端口
// InetAddress.getLocalHost() //获得主机ip
DatagramPacket datagramPacket = new DatagramPacket(data, data.length,
InetAddress.getLocalHost(), 9999);//这里的127.0.0.1指发送给本机
datagramSocket.send(datagramPacket);
//接收数据通道传来内容
byte[] buf = new byte[1024];
datagramPacket = new DatagramPacket(buf, buf.length);
datagramSocket.receive(datagramPacket);
int length = datagramPacket.getLength(); //实际接收到的数据字节长度
byte[] data2 = datagramPacket.getData(); //接收到数据
String s = new String(data2, 0, length);
System.out.println(s);
//关闭资源
datagramSocket.close();
System.out.println("===发送端已终止===");
}
}
TCP交互传输音乐文件
- 编写客户端程序和服务器端程序
- 客户端可以输入一个音乐文件名,比如高山流水,服务端收到音乐名后,可以给客户端返回这个音乐文件,如果服务器没有这个文件,返回一个默认的音乐即可.
- 客户端收到文件后,保存到本地d:\
- 该程序可以使用 StreamUtils.java
package com.tao.homework.homework03;
import com.tao.upload.StreamUtils;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
/**
* Create By 刘鸿涛
* 2022/2/9 12:21
*/
public class Homework03Client {
public static void main(String[] args) throws Exception {
//找到服务器端口
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
OutputStream outputStream = socket.getOutputStream();
System.out.println("请输入需要下载的音乐...");
Scanner scanner = new Scanner(System.in);
String downLoadFileName = scanner.next();
outputStream.write(downLoadFileName.getBytes());
socket.shutdownOutput();
//接受数据
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
byte[] bytes = StreamUtils.streamtoByteArray(bis);
//得到一个输出流,准备将bytes写入到磁盘文件
String filePath = "d:\\" + downLoadFileName + ".mp3";
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath));
bos.write(bytes);
//关闭流
outputStream.close();
socket.close();
scanner.close();
bis.close();
bos.close();
System.out.println("客户端关闭");
}
}
package com.tao.homework.homework03;
import com.tao.homework.homework01.Server;
import com.tao.upload.StreamUtils;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* Create By 刘鸿涛
* 2022/2/9 12:20
*/
public class Homework03Server {
public static void main(String[] args) throws Exception {
//1.监听 9999端口,等待客户端连接,并发送下载文件的名字
ServerSocket serverSocket = new ServerSocket(9999);
//2.等待客户端连接
Socket socket = serverSocket.accept();
//3.读取 客户端发送要下载的文件名
//这里老师使用了while读取文件名,是考虑将来客户端发送的数据较大的情况
InputStream inputStream = socket.getInputStream();
byte[] b = new byte[1024];
int len = 0;
String downLoadFileName = "";
while ((len = inputStream.read(b)) != -1){
downLoadFileName = new String (b,0,len);
}
System.out.println("客户端希望下载文件名" + downLoadFileName);
//src下有两个文件,一个是“青山”,一个“高山流水.MP3”
//如果客户下载的是 “高山流水” 我们就返回该文件,否则默认返回“青山”
String resFileName = "";
//4.创建一个输入流,读取文件
if ("高山流水".equals(downLoadFileName)){
resFileName = "src\\高山流水.mp3";
} else {
resFileName = "src\\青山.mp3";
}
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(resFileName));
//5.实用工具类StreamUtils,读取文件到一个字节数组
byte[] bytes = StreamUtils.streamtoByteArray(bis);
//6.得到Socket关联的输出流
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
//7.写入到数据通道,返回给客户端
bos.write(bytes);
socket.shutdownOutput();
//8.关闭流
serverSocket.close();
socket.close();
inputStream.close();
bis.close();
bos.close();
System.out.println("服务端退出");
}
}