0
点赞
收藏
分享

微信扫一扫

Java Socket网络编程​(四)练习

前程有光 2024-01-03 阅读 14

网络通信的练习题

TCP通信练习1---多发多收

客户端:多次发送数据

服务器:接收多次接收数据,并打印

服务器端:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class MultiReceiver {
 public static void main(String[] args) throws IOException {
 // 创建监听器
 ServerSocket ss = new ServerSocket(10086);

 // 迎接连接,并返回socket
 Socket socket = ss.accept(); // 每一个客户端对应一个Socket,因此本行代码要写在在循环外面
 // 读取数据
 InputStream is = socket.getInputStream(); // 首先获取输入流
 BufferedReader br = new BufferedReader(new InputStreamReader(is)); // 缓冲字符流
 char[] buffer = new char[1024]; // 定义读取缓冲区


 // 用socket接受数据
 int len;
 while ((len = br.read(buffer)) != -1) {
 System.out.println(new String(buffer, 0, len)); // 输出
 }

 // 关闭资源
 br.close();
 socket.close();
 ss.close();
 }
}

客户端:

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class MultiSender {
 public static void main(String[] args) throws IOException {
 /*
 客户端:多次发送数据
服务器:接收多次接收数据,并打印
 */

 // 创建Socket对象
 Socket socket = new Socket("127.0.0.1", 10086);
 OutputStream os = null;
 Scanner sc = new Scanner(System.in);
 os = socket.getOutputStream();

 while (true) {
 // 循环发送多条消息
 // 获取输出流
 System.out.print("输入要发送的消息:");
 String msg = sc.nextLine();
 if ("886".equals(msg)){ // 退出
 System.out.println("客户端退出。");
 break;
 }
 // 发送消息
 os.write(msg.getBytes());
 System.out.println("消息: " + msg + " 已发送。");
 }

 // 关闭资源
 socket.close();
 }
}


TCP通信练习2 ---接收和反馈

客户端:发送一条数据,接收服务端反馈的消息并打印

服务器:接收数据并打印,再给客户端反馈消息

客户端:

import java.io.*;
import java.net.Socket;

public class Client {
 public static void main(String[] args) throws IOException {
 // 1.创建连接
 Socket socket = new Socket("127.0.0.1", 8888);

 // 2.发送数据
 OutputStream os = socket.getOutputStream();
 String msg = "你好,服务器!";
 os.write(msg.getBytes());

 // 写出一个结束标记
 socket.shutdownOutput();

 // 3.接收数据
 InputStream is = socket.getInputStream();
 InputStreamReader isr = new InputStreamReader(is);
 int b;
 while ((b = isr.read()) != -1){
 System.out.print((char) b);
 }

 // 4.关闭资源
 socket.close();
 }
}

服务器端:

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
 public static void main(String[] args) throws IOException {
 // 1.创建监听对象
 ServerSocket ss = new ServerSocket(8888);
 // 2.等待连接
 Socket socket = ss.accept();
 // 3.接收数据
 InputStream is = socket.getInputStream();
 InputStreamReader isr = new InputStreamReader(is);
 // 读取数据
// 细节:
// read方法会从连接通道中读取数据
// 但是,需要有一个结束标记,此处的循环才会停止否则,
// 程序就会一直停在read方法这里,等待读取下面的数据
 int b;
 while ((b = isr.read()) != -1){
 System.out.print((char) b);
 }

 // 4.发送数据
 OutputStream os = socket.getOutputStream();
 os.write("你也好,客户端!".getBytes());
 /*
 OutputStreamWriter osw = new OutputStreamWriter(os);
 osw.write("你也好!");
 osw.flush(); // 使用Reader注意使用flush
 */
 socket.shutdownOutput();

 // 5.关闭连接
 socket.close();
 ss.close();
 }
}


TCP通信练习3 ---上传文件

客户端:将本地文件上传到服务器。接收服务器的反馈。

服务器:接收客户端上传的文件,上传完毕之后给出反馈。

Java Socket网络编程​(四)练习_.net


客户端:

import java.io.*;
import java.net.Socket;

public class UploadFileClient {
 public static void main(String[] args) throws IOException {
 // 上传文件客户端

 /*
 * 实现思路:
 * 1。读取本地文件,FileInputStream
 * 2。连接上服务器,Socket
 * 3。取得网络输出流getOutputStream
 * 4。一边读本地文件一边网络传送数据
 * 5。文件发送完毕后调用shutdownOutputStream()方法,向服务器说明发送完毕
 * 6。转为输入流,接受服务器发送的确认消息并回显。
 * 注意点:1。要注意关闭资源和连接
 * 2。可以使用BufferedInputStream(InputStream, size)缓冲流来提高读写性能,注意要调用flush提交数据
 */
 // 1.文件缓冲输入流
 BufferedInputStream bis = new BufferedInputStream(new FileInputStream("files/001.jpg"), 16 * 1024);
 // 2.开启Socket
 Socket socket = new Socket("localhost", 8888);
 // 3.获取网络输出流nos
 OutputStream nos = socket.getOutputStream();
 // 4.边读文件边传输
 byte[] readBuffer = new byte[16 * 1024];
 int len;
 while ((len = bis.read(readBuffer)) != -1) {
 nos.write(readBuffer, 0, len);
 }
 // 关闭文件输入流
 bis.close();
 // 关闭输出流
 nos.flush();
 //nos.close(); // 不能关闭OutputStream或者InputStream,否则将导致Socket关闭,只能通过Socket对象的shutdownOutput或shutdownInput发送结束标识

 // 5.输出结束标记
 socket.shutdownOutput();


 // 6.转为输入流,读取数据
 InputStreamReader isr = new InputStreamReader(socket.getInputStream());
 int ch;
 while ((ch = isr.read()) != -1) {
 System.out.print((char) ch);
 }

 // 关闭
 isr.close();
 socket.close();
 }
}

服务器端:

import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class UploadFileServer {
 public static void main(String[] args) throws IOException {
 // 接收服务器端

 // 监听8888端口
 ServerSocket ss = new ServerSocket(8888);

 // 获取连接通道
 Socket socket = ss.accept();

 // 获取输入流,转为缓冲流
 BufferedInputStream bis = new BufferedInputStream(socket.getInputStream(), 16 * 1024);
 byte[] readBuffer = new byte[16 * 1024];
 int len;
 // 保存到本地文件,加上时间戳防止文件重名覆盖
 FileOutputStream fos = new FileOutputStream("upload/uploadimg" + System.currentTimeMillis() + ".jpg");
 while ((len = bis.read(readBuffer)) != -1) {
 fos.write(readBuffer, 0, len);
 }
 fos.flush();
 fos.close();

 // 转为输出流
 // 向客户端发送接收完毕的消息
 OutputStreamWriter osw = new OutputStreamWriter(socket.getOutputStream());
 osw.write("文件接收完毕,谢谢!");
 osw.flush();
 osw.close();

 // 关闭流
 socket.close();
 ss.close();

 }
}


TCP通信练习4---上传文件(文件名重复问题)

解决上一题文件名重复问题

(见上一题代码,加时间戳)

UUID类

要解决文件重名的问题,可以考虑使用UUID类,使用该类UUID.randomUUID();静态方法获取UUID对象,再使用UUID.toString()获取UUID字符串。

import java.util.UUID;

public class UUIDTest {
 public static void main(String[] args) {
 UUID uuid = UUID.randomUUID();
 System.out.println(uuid.toString().replace("-", ""));
 }
}



TCP通信练习5---上传文件(多线程版)

想要服务器不停止,能接收很多用户上传的图片。该怎么做呢?

提示:可以用循环或者多线程。但是循环不合理,最优解法是用多线程改写

只需对服务器端的代码进行改动即可:

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class UploadFileServer {
 public static void main(String[] args) throws IOException {
 // 接收服务器端 (多线程版)

 // 监听8888端口
 ServerSocket ss = new ServerSocket(8888);

 while (true) {
 // 获取连接通道
 Socket socket = ss.accept();

 // 开启新线程,处理请求
 new Thread(new MyRunnable(socket)).start();
 }
 }
}

线程任务代码:

import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.UUID;

/*
 * 用于创建线程处理多用户的上传请求
 */
public class MyRunnable implements Runnable{
 // 成员变量
 private Socket socket;

 /**
 * 构造方法
 * @param socket
 */
 public MyRunnable(Socket socket){
 this.socket = socket;
 }

 @Override
 public void run() {

 try {
 // 获取输入流,转为缓冲流
 BufferedInputStream bis = new BufferedInputStream(socket.getInputStream(), 16 * 1024);
 byte[] readBuffer = new byte[16 * 1024];
 int len;
 // 保存到本地文件
 FileOutputStream fos = new FileOutputStream("upload/" + UUID.randomUUID().toString() + "uploadimg.jpg");
 while ((len = bis.read(readBuffer)) != -1) {
 fos.write(readBuffer, 0, len);
 }
 fos.flush();
 fos.close();

 // 关闭流
 socket.close();

 } catch (IOException e) {
 throw new RuntimeException(e);
 } finally {
 // 释放资源
 if (socket != null){
 try {
 socket.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 }
 }
}



TCP通信练习6 ---上传文件(线程池优化)

频繁创建线程并销毁非常浪费系统资源,所以需要用线程池优化。修改服务器端代码即可:

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class UploadFileServer {
 public static void main(String[] args) throws IOException {
 // 接收服务器端 (多线程版,线程池)

 // 创建线程池
 ThreadPoolExecutor pool = new ThreadPoolExecutor(
 3, // 核心线程数量
 16, // 线程池总大小
 60, // 空闲时间
 TimeUnit.SECONDS, // 空闲时间的单位
 new ArrayBlockingQueue<>(2), // 队列
 Executors.defaultThreadFactory(), // 线程工厂,让线程池如何创建线程对象
 new ThreadPoolExecutor.AbortPolicy() // 阻塞队列
 );

 // 监听8888端口
 ServerSocket ss = new ServerSocket(8888);

 while (true) {
 // 获取连接通道
 Socket socket = ss.accept();

 // 开启新线程,处理请求
 pool.submit(new MyRunnable(socket));
 }
 }
}



TCP通信练习7---BS(接收浏览器的消息并打印)

客户端:不需要写

服务器:接收数据并打印。




TCP通信练习8 ---网络编程(课后大作业)

控制台版的聊天室


举报

相关推荐

0 条评论