簡體   English   中英

Java 互操作——Netty + Clojure

[英]Java Interop — Netty + Clojure

我正在嘗試通過 clojure 使用 netty。 我能夠啟動服務器,但是,它無法初始化接受的套接字。 下面分別是錯誤信息和代碼。 有誰知道什么是/或可能是錯的? 我相信問題出在(Channels/pipeline (server-handler))謝謝。

錯誤信息

#<NioServerSocketChannel [id: 0x01c888d9, /0.0.0.0:843]>
Jun 6, 2012 12:15:35 PM org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink
WARNING: Failed to initialize an accepted socket.
java.lang.IllegalArgumentException: No matching method found: pipeline

項目.clj

(defproject protocol "1.0.0-SNAPSHOT"
  :description "Upload Protocol Server"
  :dependencies [
    [org.clojure/clojure "1.2.1"]
    [io.netty/netty "3.4.5.Final"]])

核心文件

(ns protocol.core
    (:import (java.net InetSocketAddress)
             (java.util.concurrent Executors)
             (org.jboss.netty.bootstrap ServerBootstrap)
             (org.jboss.netty.channel Channels ChannelPipelineFactory SimpleChannelHandler)
             (org.jboss.netty.channel.socket.nio NioServerSocketChannelFactory)
             (org.jboss.netty.buffer ChannelBuffers)))

(def policy
    "<content>Test</content>")


(defn server-handler
    "Returns netty handler."
    []
    (proxy [SimpleChannelHandler] []
        (messageReceived [ctx e]
            (let [ch (.getChannel e)]
                (.write ch policy)
                (.close ch)))

        (channelConnected [ctx e]
            (let [ch (.getChannel e)]
                (.write ch policy)
                (.close ch)))

        (exceptionCaught [ctx e]
            (let [ex (.getCause e)]
                (println "Exception" ex)
                (-> e .getChannel .close)))))

(defn setup-pipeline
    "Returns channel pipeline."
    []
    (proxy [ChannelPipelineFactory] []
        (getPipeline []
            (Channels/pipeline (server-handler)))))

(defn startup
    "Starts netty server."
    [port]
    (let [channel-factory (NioServerSocketChannelFactory. (Executors/newCachedThreadPool) (Executors/newCachedThreadPool))
          bootstrap (ServerBootstrap. channel-factory)]
        (.setPipelineFactory bootstrap (setup-pipeline))
        (.setOption bootstrap "child.tcpNoDelay" true)
        (.setOption bootstrap "child.keepAlive" true)
        (.bind bootstrap (InetSocketAddress. port))))

您的代碼存在三個問題

  1. Java 與可變參數 Channels.channel() 方法的互操作。 您可以制作一個通道處理程序向量並用(into-array ChannelHandler ..)

  2. 您不能將 String 對象直接寫入 Netty 通道。 您必須先將字符串寫入 ChannelBuffer 並寫入該緩沖區或使用 StringCodecHandler。

  3. 寫入 Netty 通道是異步的,因此您不能立即關閉它。 您必須注冊一個未來的偵聽器並在完成后關閉通道。

這是工作代碼。

  (ns clj-netty.core
   (:import (java.net InetSocketAddress)
            (java.util.concurrent Executors)
            (org.jboss.netty.bootstrap ServerBootstrap)
            (org.jboss.netty.buffer ChannelBuffers)
            (org.jboss.netty.channel Channels ChannelFutureListener ChannelHandler ChannelPipelineFactory SimpleChannelHandler)
           (org.jboss.netty.channel.socket.nio NioServerSocketChannelFactory)
           (org.jboss.netty.buffer ChannelBuffers)))


(def policy
  (ChannelBuffers/copiedBuffer
    (.getBytes "<content>Test</content>")))


(defn server-handler
  "Returns netty handler."
  []
  (proxy [SimpleChannelHandler] []
    (messageReceived [ctx e]
      (let [ch (.getChannel e)]
        (.addListener
          (.write ch policy)
          (ChannelFutureListener/CLOSE))))

    (channelConnected [ctx e]
      (let [ch (.getChannel e)]
        (.addListener
          (.write ch policy)
          (ChannelFutureListener/CLOSE))))

    (exceptionCaught [ctx e]
      (let [ex (.getCause e)]
        (println "Exception" ex)
        (-> e .getChannel .close)))))

(defn setup-pipeline
  "Returns channel pipeline."
  []
  (proxy [ChannelPipelineFactory] []
    (getPipeline []
      (let [handler (server-handler)]
        (Channels/pipeline (into-array ChannelHandler [handler]))))))



 (defn startup
      "Starts netty server."
      [port]
      (let [channel-factory (NioServerSocketChannelFactory. (Executors/newCachedThreadPool) (Executors/newCachedThreadPool))
            bootstrap (ServerBootstrap. channel-factory)]
        (.setPipelineFactory bootstrap (setup-pipeline))
        (.setOption bootstrap "child.tcpNoDelay" true)
        (.setOption bootstrap "child.keepAlive" true)
        (.bind bootstrap (InetSocketAddress. port))))

看看Aleph (也使用 Netty),它可以用許多不同的協議和漂亮的 Clojure API 來構建客戶端和服務器。

2021 年,在 Netty 之上構建 Clojure 服務的最簡單方法是采用 Donkey,它提供了與使用 Netty 作為后端的 Vert.x 的良好 Clojure 互操作。 Donkey 相對較新,還沒有很多文檔,因此請查看此博客,其中涵蓋了架構、設計、編碼和負載測試方面的相關開源項目(源代碼可用)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM