Java Network 01 - Socket and IO

该文只涉及Socket和IO(不含NIO)


网络跟我们息息相关

复习经典网络结构

OSI七层模型
数据封装过程
实际上使用的TCP/IP模型
网络协议

Socket

端点通信

Berkeley sockets is a Unix application programming interface (API) for Internet sockets and Unix domain sockets, used for inter-process communication (IPC). It is commonly implemented as a libraryof linkable modules. It originated with the 4.2BSD Unix released in 1983.
A socket is an abstract representation (handle) for the local endpoint of a network communication path. The Berkeley sockets API represents it as a file descriptor (file handle) in the Unix philosophy that provides a common interface for input and output to streams of data.
<<from wikipedia>>


socket通信

为了易懂,程序直接拷贝过来,没有使用接口继承等方式。

服务端程序1

package com.loyotech.bigscreenbackend.socket;

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

/**
 * @program big-screen-backend
 * @description 网络互联, 发送消息
 * @author Rudolph Browne
 * @create 19-1-12
 */
public class ServerSocket1 {
    public static void main(String[] args) throws IOException {

        // 暴露服务, 端点地址: 本机IP和8888
        try(ServerSocket server = new ServerSocket(8888);
            Socket socket = server.accept()) {

            System.out.println("与客户端连接成功...");
            acceptMessage(socket);
            sendMessage(socket, "Connection Success", "服务端消息");
        }
    }

    /**
     * 发送1M的消息
     * @param socket
     * @param message
     * @throws IOException
     */
    private static void sendMessage(Socket socket, String message, String messageType) throws IOException {
        OutputStream messageOut = socket.getOutputStream();
        messageOut.write((messageType + " : " + message).getBytes());
        socket.shutdownOutput();
    }

    /**
     * 读取1M数据量的消息
     * @param socket
     * @throws IOException
     */
    private static void acceptMessage(Socket socket) throws IOException {
        InputStream messageIn = socket.getInputStream();
        byte[] buf = new byte[1024];
        int len = messageIn.read(buf);
        System.out.println(new String(buf, 0, len));
        socket.shutdownInput();
    }
}

客户端程序1

package com.loyotech.bigscreenbackend.socket;

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

/*
 * @program big-screen-backend
 * @description
 * @author Rudolph Browne
 * @create 19-1-12
 */
public class ClientSocket1 {
    public static void main(String[] args) throws IOException {

        try(Socket socket = new Socket("192.168.0.104", 8888)) {

            sendMessage(socket, "Test Connection", "客户端消息");
            acceptMessage(socket);
        }
    }

    /**
     * 发送1M的消息
     * @param socket
     * @param message
     * @throws IOException
     */
    private static void sendMessage(Socket socket, String message, String messageType) throws IOException {
        OutputStream messageOut = socket.getOutputStream();
        messageOut.write((messageType + " : " + message).getBytes());
        socket.shutdownOutput();
    }

    /**
     * 读取1M数据量的消息
     * @param socket
     * @throws IOException
     */
    private static void acceptMessage(Socket socket) throws IOException {
        InputStream messageIn = socket.getInputStream();
        byte[] buf = new byte[1024];
        int len = messageIn.read(buf);
        System.out.println(new String(buf, 0, len));
        socket.shutdownInput();
    }
}

数据传输

传统数据传输通道
相同的抽象-文件

服务端程序2

package com.loyotech.bigscreenbackend.socket;

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

/**
 * @program big-screen-backend
 * @description 网络互联, 发送消息
 * @author Rudolph Browne
 * @create 19-1-12
 */
public class ServerSocket2 {
    public static void main(String[] args) throws IOException {

        // 暴露服务, 端点地址: 本机IP和8888
        try(ServerSocket server = new ServerSocket(8888);
            Socket socket = server.accept()) {

            System.out.println("与客户端连接成功...");
            sendFile(socket, new File("/home/harry/Desktop/Spring揭秘.pdf"));
        }
    }

    /**
     * 发送1M的消息
     * @param socket
     * @param fileDescriptor
     * @throws IOException
     */
    private static void sendFile(Socket socket, File fileDescriptor) throws IOException {

        try(FileInputStream fileInputStream = new FileInputStream(fileDescriptor)) {

            OutputStream packageOut = socket.getOutputStream();

            byte[] buf = new byte[1024]; // 1M大小的缓冲区
            int len = -1; // 每次读文件流大小

            while((len = fileInputStream.read(buf)) != -1) {
                packageOut.write(buf, 0, len);
            }

            System.out.println("成功将文件"+ fileDescriptor.getAbsolutePath()
                    + "发送至" + socket.getInetAddress().getHostAddress());

            socket.shutdownOutput();
        }

    }

    /**
     * 读取1M数据量的消息
     * @param socket
     * @throws IOException
     */
    private static void acceptFile(Socket socket, File fileDescriptor) throws IOException {
        try(FileOutputStream fileOutputStream = new FileOutputStream(fileDescriptor)) {
            InputStream pacakageIn = socket.getInputStream();
            byte[] buf = new byte[1024];
            int len = -1;
            while ((len = pacakageIn.read(buf)) != -1){
                fileOutputStream.write(buf, 0, len);
            }
            socket.shutdownInput();
        }
        System.out.println("从 " + socket.getInetAddress().getHostAddress() + " 接收数据," +
                "数据写入成功,存储位置: " + fileDescriptor.getAbsolutePath());
    }
}

客户端程序2

package com.loyotech.bigscreenbackend.socket;

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

/*
 * @program big-screen-backend
 * @description
 * @author Rudolph Browne
 * @create 19-1-12
 */
public class ClientSocket2 {
    public static void main(String[] args) throws IOException {

        try(Socket socket = new Socket("192.168.0.104", 8888)) {

            acceptFile(socket, new File("/media/harry/OS/Users/Rudolph Browne/WorkingSpace/揭秘.pdf"));
        }
    }

    /**
     * 发送1M的消息
     * @param socket
     * @param fileDescriptor
     * @throws IOException
     */
    private static void sendFile(Socket socket, File fileDescriptor) throws IOException {

        try(FileInputStream fileInputStream = new FileInputStream(fileDescriptor)) {

            OutputStream packageOut = socket.getOutputStream();

            byte[] buf = new byte[1024]; // 1M大小的缓冲区
            int len = -1; // 每次读文件流大小

            while((len = fileInputStream.read(buf)) != -1) {
                packageOut.write(buf, 0, len);
            }

            System.out.println("成功将文件"+ fileDescriptor.getAbsolutePath()
                    + "发送至" + socket.getInetAddress().getHostAddress());

            socket.shutdownOutput();
        }

    }

    /**
     * 读取1M数据量的消息
     * @param socket
     * @throws IOException
     */
    private static void acceptFile(Socket socket, File fileDescriptor) throws IOException {
        try(FileOutputStream fileOutputStream = new FileOutputStream(fileDescriptor)) {
            InputStream pacakageIn = socket.getInputStream();
            byte[] buf = new byte[1024];
            int len = -1;
            while ((len = pacakageIn.read(buf)) != -1){
                fileOutputStream.write(buf, 0, len);
            }
            socket.shutdownInput();
        }
        System.out.println("从" + socket.getInetAddress().getHostAddress() + "接收数据," +
                "数据写入成功,存储位置: " + fileDescriptor.getAbsolutePath());
    }
}

支持多用户并发上传下载文件

做法是使用多线程, 非NIO版本

服务端程序3

package com.loyotech.bigscreenbackend.socket;

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

/**
 * @program big-screen-backend
 * @description 支持多用户下载文件
 * @author Rudolph Browne
 * @create 19-1-12
 */
public class ServerSocket3 {
    public static void main(String[] args) throws IOException {

        // 暴露服务, 端点地址: 本机IP和8888
        try(ServerSocket server = new ServerSocket(8888)){

            while (true) {
                Socket socket = server.accept();
                System.out.println("与客户端 " + socket.getInetAddress().getHostAddress() + " 连接成功...");
                new Thread(new MyDownloadFileSocketHelper(socket,
                        new File("/home/harry/Desktop/Spring揭秘.pdf"))).start();
            }
        }


    }

    /**
     * 发送1M的消息
     * @param socket
     * @param fileDescriptor
     * @throws IOException
     */
    private static void sendFile(Socket socket, File fileDescriptor) throws IOException {

        try(FileInputStream fileInputStream = new FileInputStream(fileDescriptor)) {

            OutputStream packageOut = socket.getOutputStream();

            byte[] buf = new byte[1024]; // 1M大小的缓冲区
            int len = -1; // 每次读文件流大小

            while((len = fileInputStream.read(buf)) != -1) {
                packageOut.write(buf, 0, len);
            }

            System.out.println("成功将文件"+ fileDescriptor.getAbsolutePath()
                    + "发送至" + socket.getInetAddress().getHostAddress());

            socket.shutdownOutput();
        }

    }

    private static class MyDownloadFileSocketHelper implements Runnable {

        private Socket socket;
        private File fileDescriptor;

        public MyDownloadFileSocketHelper(Socket socket, File fileDescriptor){
            this.socket = socket;
            this.fileDescriptor = fileDescriptor;
        }

        @Override
        public void run() {
            try {
                sendFile(socket, fileDescriptor);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

客户端程序3

package com.loyotech.bigscreenbackend.socket;

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

/*
 * @program big-screen-backend
 * @description 支持多用户下载文件
 * @author Rudolph Browne
 * @create 19-1-12
 */
public class ClientSocket3 {
    public static void main(String[] args) throws IOException {

        try(Socket socket = new Socket("192.168.0.104", 8888)) {

            acceptFile(socket, new File("/media/harry/OS/Users/Rudolph Browne/WorkingSpace/揭秘" + Instant.now() + ".pdf"));
        }
    }

    /**
     * 读取1M数据量的消息
     * @param socket
     * @throws IOException
     */
    private static void acceptFile(Socket socket, File fileDescriptor) throws IOException {
        try(FileOutputStream fileOutputStream = new FileOutputStream(fileDescriptor)) {
            InputStream pacakageIn = socket.getInputStream();
            byte[] buf = new byte[1024];
            int len = -1;
            while ((len = pacakageIn.read(buf)) != -1){
                fileOutputStream.write(buf, 0, len);
            }
            socket.shutdownInput();
        }
        System.out.println("从" + socket.getInetAddress().getHostAddress() + "接收数据," +
                "数据写入成功,存储位置: " + fileDescriptor.getAbsolutePath());
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容