TCP 练习
- 使用字符流的方式,编写一个客户端程序和服务器端程序,客户端发送 “name”,服务器端接收到后,返回 "我是nova ",nova是你自己的名字
- 客户端发送 “hobby”,服务器端接收到后,返回 “编写java程序”
- 不是这两个问题,回复 “你说啥呢”
服务端
package net.udp;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException {
// 1. 在本机的 9999 端口进行监听,等待连接
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务端等待连接...");
// 2. 如果没有客户端连接,程序会阻塞,等待连接
// 如果有程序连接,会返回一个 Socket 对象,继续执行
Socket socket = serverSocket.accept();
// 3. 获取输入流,读取客户端输入到数据通道中的数据
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String s = bufferedReader.readLine();
System.out.println(s);
// 4. 判断客户端发送过来的数据是什么
String answer = "";
if("name".equals(s)){
answer = "我是 Gin";
} else if ("hobby".equals(s)) {
answer = "编写 Java 代码";
} else {
answer = "你说啥呢";
}
// 5. 获取输出流,将 answer 返回给客户端
OutputStream outputStream = socket.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write(answer);
bufferedWriter.newline();
bufferedWriter.flush();
// 6. 关闭资源
socket.close();
bufferedWriter.close();
bufferedReader.close();
serverSocket.close();
System.out.println("服务端退出...");
}
}
客户端
package net.udp;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) throws IOException {
// 1. 连接服务端
Socket socket = new Socket(InetAddress.getByName("10.25.135.233"), 9999);
// 2. 客户端提出的问题
System.out.println("输入你的问题:");
Scanner scanner = new Scanner(System.in);
String question = scanner.nextLine();
// 3. 获取输出流,通过字符流往数据通道中写入数据
OutputStream outputStream = socket.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write(question);
bufferedWriter.newline(); // 插入一个换行符表示写入数据完毕
bufferedWriter.flush(); // 如果使用字符流,需手动刷新,否则数据不会写入数据通道
// 4. 获取输入流,通过字符流来读取数据通道中返回过来的信息
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String s = bufferedReader.readLine();
System.out.println(s); // 输出返回过来的信息
// 5. 关闭资源
socket.close();
bufferedWriter.close();
bufferedReader.close();
System.out.println("客户端退出...");
}
}
UDP 练习
- 编写一个接收端A,和一个发送端B,使用 UDP 协议完成接收端在 8888 端口等待接收数据(receive)
- 发送端 向接收端 发送数据 “四大名著是哪些”
- 接收端接收到发送端发送的问题后,返回 “四大名著是<<红楼梦>>…”,否则返回 what?
- 接收端 和发送端 程序退出
发送端
package net.udp;
import java.io.IOException;
import java.net.*;
public class Sender {
public static void main(String[] args) throws IOException {
// 1. 创建 DatagramSocket 对象,准备在 8889 端口发送数据
DatagramSocket datagramSocket = new DatagramSocket(8889);
// 2. 将需要发送的数据封装到 DatagramPacket 对象中
byte[] bytes = "四大名著是哪些".getBytes();
DatagramPacket datagramPacket
= new DatagramPacket(bytes, bytes.length, InetAddress.getByName("10.25.135.233"), 8888);
// 3. 调用发送方法
datagramSocket.send(datagramPacket);
// 4. 准备接受数据
byte[] buf = new byte[1024];
datagramPacket = new DatagramPacket(buf, buf.length);
// 5. 调用接收方法
datagramSocket.receive(datagramPacket);
// 6. 将接收到的数据进行拆包,取出数据并显示
int length = datagramPacket.getLength();
byte[] data = datagramPacket.getData();
String s = new String(data, 0, length);
System.out.println(s);
// 7. 关闭资源
datagramSocket.close();
System.out.println("Sender 端退出...");
}
}
接收端
package net.udp;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class Receiver {
public static void main(String[] args) throws IOException {
// 1. 创建一个 DatagramSocket 对象,准备在 8888 端口接收数据
DatagramSocket datagramSocket = new DatagramSocket(8888);
// 2. 创建一个 DatagramPacket 对象,准备接受数据
// UDP 协议:每个数据包的大小限制在 64K 内,不适合传输大量数据
byte[] buf = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(buf, buf.length);
// 3. 调用接收方法
System.out.println("接收端 A 等待接收数据...");
datagramSocket.receive(datagramPacket);
// 4. 把接收到的数据进行拆包,取出数据并显示
int length = datagramPacket.getLength();
byte[] data = datagramPacket.getData();
String s = new String(data, 0, length);
System.out.println(s);
// 5. 回复数据给发送端
byte[] bytes = "四大名著是《红楼梦》《水浒传》《三国演义》《西游记》".getBytes();
datagramPacket = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("10.25.135.233"), 8889);
// 6. 通过 DatagramSocket 对象发送数据
datagramSocket.send(datagramPacket);
// 7. 关闭资源
datagramSocket.close();
System.out.println("Receiver 端退出...");
}
}
TCP 文件下载练习
- 编写客户端程序和服务器端程序
- 客户端可以输入一个音乐文件名,比如高山流水,服务端收到音乐名后,可以给客户端返回这个音乐文件,如果服务器没有这个文件,返回一个默认的音乐即可
- 客户端收到文件后,保存到本地 E:\
- 提示:该程序可以使用 StreamUtils.java
服务端
package net;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerA {
public static void main(String[] args) throws IOException {
// 1. 监听 9999 端口,等待连接
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务端在 9999 端口监听,等待连接...");
// 2. 等待连接,如有客户端连接,则返回 Socket 对象
Socket socket = serverSocket.accept();
// 3. 获取 socket 的输入流,读取客户端要下载的文件名
InputStream inputStream = socket.getInputStream();
byte[] data = new byte[1024];
int len = 0;
String downloadFilename = "";
while((len = inputStream.read(data)) != -1){
downloadFilename += new String(data, 0, len);
}
System.out.println("客户端希望下载的文件名:" + downloadFilename);
// 4. 服务器上有两个文件:Gin.mp4 和 Vodka.mp4
// 如果客户端要下载的是 Gin.mp4,就返回 Gin.mp4,其他的一律返回 Vodka.mp4
String resFilename = "";
if("Gin.mp4".equals(downloadFilename)){
resFilename = "src\Gin.mp4";
}else{
resFilename = "src\Vodka.mp4";
}
// 5. 创建一个输入流,读取文件
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(resFilename));
// 6. 使用 StreamUtils 工具类,将读读取到的文件存入一个字节数组
byte[] array = StreamUtils.streamToByteArray(bis);
// 7. 得到 socket 相关的输出流,将 array 字节数组写入数据通道
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
bos.write(array);
// 8. 设置 写入结束标记
socket.shutdownOutput();
// 9. 关闭相关资源
bos.close();
bis.close();
inputStream.close();
socket.close();
serverSocket.close();
System.out.println("服务端退出...");
}
}
客户端
package net;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;
public class ClientB {
public static void main(String[] args) throws IOException {
// 1. 接收用户输入,指定下载的文件名
Scanner scanner = new Scanner(System.in);
System.out.println("输入下载的文件名:");
String downloadFilename = scanner.nextLine();
// 2. 连接服务端
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
// 3. 获取 socket 相关的输出流,将要下载的文件名写入数据通道
OutputStream outputStream = socket.getOutputStream();
outputStream.write(downloadFilename.getBytes());
// 4. 设置写入结束标记
socket.shutdownOutput();
// 5. 读取服务端返回的文件(字节数组)
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
// 6. 通过 StreamUtils 工具类,将读取到的数据存入字节数组
byte[] array = StreamUtils.streamToByteArray(bis);
// 7. 创建一个输出流,将 array 字节数组写入磁盘
String filePath = "E:\"+ downloadFilename;
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath));
bos.write(array);
// 8. 关闭资源
bos.close();
bis.close();
socket.close();
outputStream.close();
System.out.println("客户端退出...");
}
}