网络编程——TCP通信练习

目录

一、多发多收

二、接收和反馈

三、上传文件

四、解决上传文件名重复问题

五、上传文件多线程版

六、上传文件线程池版

七、B/S(接收浏览器的消息并打印)


一、多发多收

客户端:多次发送数据

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

java 复制代码
public class Client {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1", 10010);
        Scanner scanner = new Scanner(System.in);
        OutputStream os = socket.getOutputStream();
        while (true) {
            System.out.println("请输入内容:");
            String str = scanner.nextLine();
            os.write(str.getBytes());
            if ("拜拜".equals(str)) {
                break;
            }
        }
        socket.close();
    }
}


public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(10010);
        Socket socket = serverSocket.accept();
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        int len;
        while ((len = br.read()) != -1) {
            System.out.print((char) len);
        }
        socket.close();
        serverSocket.close();
    }
}

运行结果:

二、接收和反馈

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

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

java 复制代码
public class Client {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1", 10010);

        // 写出数据
        OutputStream os = socket.getOutputStream();
        String str = "客户端发送消息:见到你很开心!";
        os.write(str.getBytes());

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

        // 读取数据
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        int len = 0;
        while ((len = br.read()) != -1) {
            System.out.print((char) len);
        }

        // 释放资源
        socket.close();
    }
}

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

        // 写出数据
        OutputStream os = socket.getOutputStream();
        String str = "服务器发送消息:有多开心?";
        os.write(str.getBytes());

        // 释放资源
        socket.close();
        serverSocket.close();
    }
}

运行结果:

三、上传文件

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

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

使用FileInputStream读取本地文件,使用FileOutputStream保存本地文件

java 复制代码
public class Client {
    public static void main(String[] args) throws IOException {
        // 1.创建Socket对象,并连接服务器
        Socket socket = new Socket("127.0.0.1", 10020);
        
        // 2.读取本地文件中的数据,并写到服务器中
        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("mysocketnet/clientdir/a.jpg"));
        int len;
        byte[] bytes = new byte[1024];
        while ((len = bis.read(bytes)) != -1) {
            bos.write(bytes, 0, len);
        }

        // 向服务器写出结束标记
        socket.shutdownOutput();

        // 3.接收服务器的回写数据
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String str = br.readLine();
        System.out.println(str);

        // 4.释放资源
        socket.close();
    }
}


public class Server {
    public static void main(String[] args) throws IOException {
        // 1.创建对象并绑定端口
        ServerSocket serverSocket = new ServerSocket(10020);

        // 2.等待客户端来连接
        Socket socket = serverSocket.accept();

        // 3.读取客户端发送的数据,并将数据存入指定路径中
        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("mysocketnet/serverdir/a.jpg"));
        int len;
        byte[] bytes = new byte[1024];
        while ((len = bis.read(bytes)) != -1) {
            bos.write(bytes, 0, len);
        }

        // 4. 服务器向客户端回写数据
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bw.write("服务器向客户端发送消息:文件已接收!");
        bw.newLine();
        bw.flush();

        // 5.释放资源
        socket.close();
        serverSocket.close();
    }
}

运行结果:

四、解决上传文件名重复问题

Client代码无需修改

java 复制代码
public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(10020);
        Socket socket = serverSocket.accept();

        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
        // 方式一:使用毫秒值拼接
//        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("mysocketnet\\serverdir" + File.separator + System.currentTimeMillis() + ".jpg"));

        // 方式二:使用UUID拼接
        String name = UUID.randomUUID().toString().replace("-", "");
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("mysocketnet\\serverdir" + File.separator + name + ".jpg"));

        int len;
        byte[] bytes = new byte[1024];
        while ((len = bis.read(bytes)) != -1) {
            bos.write(bytes, 0, len);
        }

        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bw.write("文件上传成功!");
        bw.newLine();
        bw.flush();

        socket.close();
        serverSocket.close();
    }
}

运行结果:

五、上传文件多线程版

让服务器不停止,能接收很多用户上传的图片,可以使用(循环+多线程)

Client代码无需修改

java 复制代码
public class MyRunnable implements Runnable {
    public Socket socket;

    public MyRunnable(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
            String name = UUID.randomUUID().toString().replace("-", "");
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("mysocketnet\\serverdir" + File.separator + name + ".jpg"));

            int len;
            byte[] bytes = new byte[1024];
            while ((len = bis.read(bytes)) != -1) {
                bos.write(bytes, 0, len);
            }

            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            bw.write("文件上传成功!");
            bw.newLine();
            bw.flush();

        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(10020);

        while (true) {
            // 等待客户端来连接
            Socket socket = serverSocket.accept();

            // 一个用户对应服务端的一条线程
            new Thread(new MyRunnable(socket)).start();
        }
    }
}

先开启Server,每开启一次Client,就会创建一个线程,文件也会上传

运行结果:

六、上传文件线程池版

频繁创建线程并销毁非常浪费系统资源,所以需要用线程池优化。

只需要修改Server即可:

java 复制代码
public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(10020);

        // 创建线程池对象
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
                3, // 核心线程数量
                16, // 线程池总大小
                60, // 空闲时间
                TimeUnit.SECONDS, // 空闲时间(单位)
                new ArrayBlockingQueue<>(2), // 队列
                Executors.defaultThreadFactory(), // 线程工厂,让线程池如何创建线程对象
                new ThreadPoolExecutor.AbortPolicy() // 阻塞队列
        );
        while (true) {
            Socket socket = serverSocket.accept();
//            new Thread(new MyRunnable(socket)).start();
            poolExecutor.submit(new MyRunnable(socket));
        }
    }
}

运行结果:

七、B/S(接收浏览器的消息并打印)

客户端:不需要写

服务器:接收数据并打印

java 复制代码
public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(10010);

        Socket socket = serverSocket.accept();
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        int len;
        char[] chars = new char[1024];
        while ((len = br.read(chars)) != -1) {
            System.out.println(new String(chars, 0, len));
            br.readLine();
        }
        socket.close();
        serverSocket.close();
    }
}

浏览器输入:http://localhost:10010/

运行结果:

相关推荐
蜜桃小阿雯几秒前
JAVA开源项目 微服务在线教育系统 计算机毕业设计
java·开发语言·spring boot·微服务·java-ee·开源·maven
花下的晚风几秒前
单元测试时报错找不到@SpringBootConfiguration
java·开发语言·单元测试
卓越小Y15 分钟前
配置jellyfin docker 硬件加速
java·spring cloud·docker
白萝卜弟弟18 分钟前
【JAVA】正则表达式中的捕获组和非捕获组
java·正则表达式
袁庭新39 分钟前
LuaRocks如何安装数据库驱动?
java·数据库·redis·lua·luarocks·袁庭新
hummhumm1 小时前
第 10 章 - Go语言字符串操作
java·后端·python·sql·算法·golang·database
nukix1 小时前
Mac Java 使用 tesseract 进行 ORC 识别
java·开发语言·macos·orc
月光光心慌慌。1 小时前
新日撸java三百行` 新手小白java学习记录 `Day1
java
蘑菇丁1 小时前
ranger-kms安装
java·ide·eclipse
XiaoLeisj1 小时前
【JavaEE初阶 — 多线程】内存可见性问题 & volatile
java·开发语言·java-ee