封装socket的通信协议完成文本通信

封装socket的通信协议完成文本通信

socket是典型的cs架构,由于client端通过OutputStream发送消息,server端通过InputStream接收消息。一般发送本文信息都是一条条发出去的,接收端无法得知每条消息的边界。所以对协议封装一下完成文本信息逐条发送并在服务端实时解析。
首先约定好协议的标准

public class Protocol {
    public static final int OPEN = 1;
    public static final int TALK = 2;
    public static final int QUIT = 3;
}

socket客户端的代码

public class EchoClient implements Closeable {
    private String host;
    private int port;
    private Socket client;


    public EchoClient(String host, int port) {
        this.host = host;
        this.port = port;
        try {
            client = new Socket(host, port);
            open(client);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void open(Socket client) {
        try {
            OutputStream outputStream = client.getOutputStream();
            DataOutputStream write = new DataOutputStream(outputStream);
            write.write(Protocol.OPEN);
            write.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void sendMessage(String message) {
        try {
            byte[] data = message.getBytes("UTF-8");
            OutputStream outputStream = client.getOutputStream();
            DataOutputStream write = new DataOutputStream(outputStream);
            write.writeByte(Protocol.TALK);
            write.writeInt(data.length);
            write.write(data);
            write.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void close() throws IOException {
        OutputStream outputStream = null;
        try {
            outputStream = client.getOutputStream();
            DataOutputStream write = new DataOutputStream(outputStream);
            write.write(Protocol.QUIT);
            write.flush();
            write.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        client.close();
    }

    public static void main(String[] args) {
        try (EchoClient client = new EchoClient("localhost", 55533)) {
            for (int i = 0; i < 5000; i++) {
                client.sendMessage(String.format("hello world %s", i));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

socket服务端的代码

public class EchoServer implements Closeable, Runnable {
    private int port;
    private ServerSocket server;
    private boolean RUNNINGSTATE = false;

    public EchoServer(int port) {
        this.port = port;
        try {
            server = new ServerSocket(port);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void listener() {
        Socket client = null;
        try {
            client = server.accept();
        } catch (IOException e) {
            e.printStackTrace();
        }
        accept(client);
    }

    @Override
    public void run() {
        listener();
    }

    public void onOpen(Socket socket) {
        RUNNINGSTATE = true;
        System.out.println(String.format("新连接%s进来了", socket.getInetAddress()));
    }

    public void onClose(Socket socket) {
        System.out.println(String.format("客户端%s退出连接", socket.getInetAddress()));
    }

    public void handle(String message) {
        System.out.println(message);
    }

    public void accept(Socket socket) {
        try {
            InputStream inputStream = socket.getInputStream();
            BufferedInputStream read = new BufferedInputStream(inputStream);
            int type = 0;
            while ((type = read.read()) != -1) {
                switch (type) {
                    case Protocol.OPEN:
                        onOpen(socket);
                        break;
                    case Protocol.QUIT:
                        onClose(socket);
                        break;
                    case Protocol.TALK:
                        byte[] buffer = new byte[1024];
                        int len = readInt(read);
                        int offset = 0;
                        StringBuilder sb = new StringBuilder();
                        while (len > 0 && (offset = read.read(buffer, 0, len < buffer.length ? len : buffer.length)) != -1) {
                            sb.append(new String(buffer, 0, offset, "UTF-8"));
                            len -= offset;
                        }
                        handle(sb.toString());
                }
            }
            read.close();
            inputStream.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public final int readInt(InputStream in) throws IOException {
        int ch1 = in.read();
        int ch2 = in.read();
        int ch3 = in.read();
        int ch4 = in.read();
        if ((ch1 | ch2 | ch3 | ch4) < 0)
            throw new EOFException();
        return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
    }

    public boolean isRUNNINGSTATE() {
        return RUNNINGSTATE;
    }

    public static void main(String[] args) {
        EchoServer echoServer = new EchoServer(55533);
        echoServer.run();
    }

    @Override
    public void close() throws IOException {
        server.close();
    }
}

然后启动服务端和客户端即可完成消息的发送和接受

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值