Java Interop - Netty + Clojure

I am trying to use netty through clojure. I can start the server, however it cannot initialize the received socket. The following are error messages and code respectively. Does anyone know what may or may be wrong? I believe the problem is with (Channels/pipeline (server-handler)) Thanks.

Error message

 #<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
source share
1 answer

There are three problems in your code.

  • Java interaction with the vararg Channels.channel () method. you can make a channel handler vector and wrap it with (into-array ChannelHandler ..)

  • You cannot write String objects directly to the Netty Channel. you must first write the string to ChannelBuffer and write this buffer or use StringCodecHandler.

  • Writing to a Netty channel is asynchronous, so you cannot close it right away. You must register the future listener and close the channel when this is done.

Here is the working code.

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

Check out Aleph (also using Netty), which can be used to create clients and servers in many different protocols with a nice Clojure API.

+6
source

Source: https://habr.com/ru/post/917462/


All Articles