2012-06-06 14 views
6

मैं क्लोजर के माध्यम से नेटटी का उपयोग करने की कोशिश कर रहा हूं। मैं सर्वर को स्टार्टअप करने में सक्षम हूं, हालांकि, यह एक स्वीकृत सॉकेट शुरू करने में विफल रहता है। नीचे क्रमशः त्रुटि संदेश और कोड हैं। क्या किसी को पता है कि क्या गलत है या गलत हो सकता है? मुझे विश्वास है कि यह मुद्दा (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 

project.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"]]) 

core.clj

(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)))) 

उत्तर

6

रहे हैं तीन समस्याओं आपके कोड

  1. vararg Channels.channel() विधि के साथ जावा इंटरऑप के साथ। आप चैनल हैंडलर का वेक्टर बना सकते हैं और (into-array ChannelHandler ..)

  2. आप स्ट्रिंग ऑब्जेक्ट्स को सीधे नेटी चैनल पर नहीं लिख सकते हैं। आपको स्ट्रिंग को पहले चैनलबफर में लिखना है और उस बफर को लिखना है या स्ट्रिंगकोडेक हैंडलर का उपयोग करना है।

  3. नेटटी चैनल को लिखना एसिंक्रोनस है, इसलिए आप इसे तुरंत बंद नहीं कर सकते हैं। आपको भविष्य के श्रोता को पंजीकृत करना होगा और इसे पूरा होने पर चैनल बंद करना होगा।

यहां कामकाजी कोड है।

(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 एपीआई के साथ कई अलग अलग प्रोटोकॉल में क्लाइंट और सर्वर का निर्माण करने के लिए इस्तेमाल कर सकते हैं है।

+0

स्पष्ट और विस्तृत स्पष्टीकरण के लिए धन्यवाद, यह बहुत उपयोगी था। मैं निश्चित रूप से, एलेफ की कोशिश करने की योजना बना रहा हूं, लेकिन मुझे लगा कि मुझे एक पत्थर के साथ दो पक्षी मिलेंगे - क्लोजर का अभ्यास करते समय नेटटी सीखें। – Ari

संबंधित मुद्दे