Socket通讯的简单实现与应用(文件上传)

Socket通讯的基本实现

package com.yusian.socket;

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

public class SocketDemo {
    public static void main(String[] args) {
        // 服务端进程
        new Thread(() -> {
            try {
                // 创建一个Socket服务
                ServerSocket ss = new ServerSocket(8080);
                // 获取Socket的字节输入流对象,此时程序会阻塞在这个位置,直到有数据
                InputStream is = ss.accept().getInputStream();
                int data = 0;
                // 将接收到的数据输出到控制台
                while ((data = is.read()) != -1) {
                    System.out.print((char) data);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();

        // 客户端进程
        new Thread(() -> {
            try {
                // 创建一个Socket客户端,连接到指定服务器
                Socket s = new Socket("localhost", 8080);
                // 获取Socket的字节输出流,将数据从这里发出
                OutputStream os = s.getOutputStream();
                os.write("Hello Socket...".getBytes());
                // 注意:要主动结束数据发送,否则对方会一直处于等待状态
                s.shutdownOutput();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

多线程文件上传

Client

package com.yusian.socket;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class Client {
    public static void main(String[] args) {
        try {
            // Socket通讯使用Socket中的字节流
            Socket socket = new Socket("localhost", 8080);
            OutputStream os = socket.getOutputStream();
            // 读取本地文件使用本地字节流
            FileInputStream fis = new FileInputStream("2.txt");
            int length = 0;
            byte[] buffer = new byte[8192];
            while((length = fis.read(buffer)) != -1) {
                os.write(buffer, 0, length);
            }
            // 发送结束标记
            socket.shutdownOutput();
            System.out.println("发送完毕...");
            // 获取服务器发来的数据,使用Socket中的字节流
            InputStream is = socket.getInputStream();
            int data = 0;
            while((data = is.read()) != -1) {
                System.out.print((char) data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Server

package com.yusian.socket;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Server {
    public static void main(String[] args) {
        try {
            ServerSocket ss = new ServerSocket(8080);
            ExecutorService es = Executors.newFixedThreadPool(3);
            while (true) {
                // 程序会阻塞在accept()方法,直到有客户端连接上来
                Socket socket = ss.accept();
                // 线程池中拿出一个线程执行接收任务
                es.submit(() -> fileRecieve(socket));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 文件接收
    private static void fileRecieve(Socket socket) {
        try {
            // 获取输入字节流
            InputStream is = socket.getInputStream();
            // 创建文件输出字节流
            FileOutputStream fos = new FileOutputStream("1.txt");
            int length = 0;
            byte[] buffer = new byte[1024];
            // 将从Socket输入流的数据通过文件输出流写入到本地文件
            while ((length = is.read(buffer)) != -1) {
                fos.write(buffer, 0, length);
            }
            System.out.println("接收完毕...");
            // 接收完毕后通过Socket的输出流,回复消息给客户端
            OutputStream os = socket.getOutputStream();
            os.write("Server: Complete...".getBytes());
            // 注意:socket中的输出流需要通过调用shutdownOutput方法来结束输出
            socket.shutdownOutput();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Leave a Reply