smart-socket如何實現字符串通訊

很多的朋友在接觸到smart-socket後,一上來就想寫一個字符串通訊的案例。例如客戶端發送"Hello Server!",服務端接收到該消息並響應"Hi Client!"。但最終發現客戶端能夠成功將消息發送出去,但服務端就是沒法正常接收。那是否是這個smart-socket框架不行?爲何原先用Netty很簡單就實現了?java

也許您是第一次接觸通訊,又或者此前有過一些通訊編程經歷,但只要沒法用smart-socket寫出一個簡單的字符串通訊示例,那說明您的通訊之旅還未入門。本文儘可能給你們解釋清楚通訊編程的常見套路,此後你們能夠輕鬆玩轉socket。git

咱們以兩我的的對話場景爲例,A對B說:"我叫A我今年3歲"。從這句話中,咱們很容易解讀出A對B傳遞了兩個消息,一個是「我叫A」,另外一個是「我今年3歲」。人爲識別一句話是一件很天然的事,咱們甚至不用去思考爲何咱們能夠從一句話中解讀出多個消息,那是一種本能。在這個本能的背後有一套很是複雜的「算法」在幫你準確的識別並分析平常交流的信息。可是在計算機要模擬現實世界的信息通訊場景,就須要由程序員爲機器賦予消息識別能力,這個能力也是通訊中很是重要的環節:信息編解碼。程序員

一樣是「我叫A我今年3歲」,人能夠經過逐個文字讀取,結合上下文的語義分析識別,最終解析出兩個消息,而將這套算法轉換成機器算法倒是一件很是困難的事。不過咱們能夠採用機器更容易接受的方式來實現這個功能,接下里給你們介紹兩種。算法

方案一

首先,兩個通訊機器能夠事先約定好在每個消息以前,先告訴對方這個消息長度多少,這樣在傳輸的過程當中不管一次性傳遞多少個消息,對方都能準確識別出。例如機器A與機器B的通訊方式能夠是這樣的。A告知B:「這個消息3個字,我叫A,這個消息5個字,我今年3歲」,網絡傳輸的形態就是「3我叫A5我今年3歲」。機器B收到這串內容以後就很容易解析出A傳遞的兩個消息,只要先識別出即將解析消息的長度,再讀取指定長度的數據即是一個完整的消息。編程

方案二

機器A能夠與機器B約定好「接下來個人消息都以某個分割符爲標誌,且這個分隔符確定不會出現於消息內容中的」。好比雙方約定好的分隔符爲逗號,那麼雙方通訊的內容自己必然不能出現該符號。此時機器A傳輸給B的數據爲「我叫A,我今年3歲,」,機器B經過分隔符便識別出了兩個消息。網絡

總之你們要謹記兩點:session

  1. 你的程序沒有識別白話文的能力;
  2. 絕大部分的通訊編解碼均可按照本文提供的兩種方案處理。

若是您的悟性還不錯的話,文章看到此處便完結了。若是本文解釋的還不夠清楚,那接下來用代碼來給你們示範方案一的實現。框架

  1. 約定雙方通訊的編解碼協議
/**
 * @author 三刀
 * @version V1.0 , 2018/8/25
 */
public class StringProtocol implements Protocol<String> {

    private static final int INT_LENGTH = 4;

    @Override
    public String decode(ByteBuffer readBuffer, AioSession<String> session, boolean eof) {
        //識別消息長度
        if (readBuffer.remaining() < INT_LENGTH) {
            return null;
        }
        //判斷是否存在半包狀況
        int len = readBuffer.getInt(0);
        if (readBuffer.remaining() < len) {
            return null;
        }
        readBuffer.getInt();//跳過length字段
        byte[] bytes = new byte[len - INT_LENGTH];
        readBuffer.get(bytes);
        return new String(bytes);
    }

    @Override
    public ByteBuffer encode(String msg, AioSession<String> session) {
        byte[] bytes = msg.getBytes();
        ByteBuffer buffer = ByteBuffer.allocate(INT_LENGTH + bytes.length);
        buffer.putInt(INT_LENGTH + bytes.length);
        buffer.put(bytes);
        buffer.flip();
        return buffer;
    }
}
  1. 服務端實現消息處理邏輯並啓動服務
/**
 * @author 三刀
 * @version V1.0 , 2018/8/25
 */
public class StringServerProcessor implements MessageProcessor<String> {
    public static void main(String[] args) throws IOException {
        AioQuickServer<String> server = new AioQuickServer<>(8080, new StringProtocol(), new StringServerProcessor());
        server.start();
    }

    @Override
    public void process(AioSession<String> session, String msg) {
        System.out.println("收到客戶端消息:" + msg);
        try {
            session.write("服務端收到了你的消息:" + msg);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void stateEvent(AioSession<String> session, StateMachineEnum stateMachineEnum, Throwable throwable) {

    }
}
  1. 客戶端發送消息並接受服務的響應
/**
 * @author 三刀
 * @version V1.0 , 2018/8/25
 */
public class StringClientProcessor implements MessageProcessor<String> {
    private AioSession<String> session;

    public static void main(String[] args) throws IOException, InterruptedException, ExecutionException {
        StringClientProcessor processor = new StringClientProcessor();
        AioQuickClient<String> client = new AioQuickClient<>("localhost", 8080, new StringProtocol(), processor);
        client.start();
        int i = 0;
        while (i++ < 10) {
            processor.getSession().write("Hello:" + i);
        }
        Thread.sleep(1000);
        client.shutdown();
    }

    @Override
    public void process(AioSession<String> session, String msg) {
        System.out.println("收到服務端消息:" + msg);
    }

    @Override
    public void stateEvent(AioSession<String> session, StateMachineEnum stateMachineEnum, Throwable throwable) {
        if (stateMachineEnum == StateMachineEnum.NEW_SESSION) {
            this.session = session;
        }
    }

    public AioSession<String> getSession() {
        return session;
    }
}

若是您是堅持到文末的讀者,但願能Star並支持一下咱們的項目smart-socket,多謝!socket

相關文章
相關標籤/搜索