Mina, Netty, twisted Together (vii): Publish/Subscribe (publish/subscribe)

Source: Internet
Author: User
Tags throwable

There are many ways to message delivery, and request/response (request/reply) is the most common. In the example in the previous blog post, many are in Request/response mode, and when the server receives the message, it immediately writes back a message to the client. The HTTP protocol is also based on the request/response approach.

However, the request/response does not meet all the messaging requirements, and some requirements may require the server to proactively push the message to the client instead of passively waiting for the request to respond.

Publish/Subscribe (Publish/subscribe) is a way for a server to send messages to the client proactively. After the Subscriber Subscriber connects to the server client, it is equivalent to starting a subscription to Publisher Publisher's message, and when the publisher publishes a message, all subscribers receive the message.

Web chat rooms are typically implemented based on a publish/subscribe model. For example, join a QQ group, it is equivalent to subscribe to all the messages of this group, when there are new messages, the server will actively send messages to all clients. But everyone in the chat room is both a publisher and a subscriber.

The following respectively, with Mina, Netty, twisted to implement a simple publish/subscribe mode of the server program, all the clients connected to the server are subscribers, when the publisher publishes a message, the server forwards the message to all clients.

MINA:

In Mina, the Ioservice getmanagedsessions () method can be used to obtain all iosession currently managed by this ioservice, that is, all the client collections connected to the server. When the server receives a message published by the publisher, the Ioservice getmanagedsessions () method can be used to obtain iosession for all clients and send messages to those clients.

public class TCPServer {public static void main (string[] args) throws IOException {Ioacceptor acceptor = new Niosocketacce Ptor (); Acceptor.getfilterchain (). AddLast ("Codec", new Protocolcodecfilter (New Textlinecodecfactory ( Charset.forname ("UTF-8"), "\ r \ n", "\ r \ n")), Acceptor.sethandler (New Tcpserverhandle ()); Acceptor.bind (new Inetsocketaddress (8080));}} Class Tcpserverhandle extends Iohandleradapter {@Overridepublic void Exceptioncaught (iosession session, Throwable cause ) throws Exception {Cause.printstacktrace ();} @Overridepublic void Messagereceived (iosession session, Object message) throws Exception {// Gets all connected iosessioncollection<iosession> sessions = Session.getservice (). Getmanagedsessions (). values ();// Writes the message to all Iosessionioutil.broadcast (message, sessions);}}

Netty:

Netty provides channelgroup for saving the channel group, Channelgroup is a thread-safe collection of channel, which provides some column channel bulk operations. When a TCP connection is closed, the corresponding channel is automatically removed from the Channelgroup, so no manual removal of the closed channel is necessary.

Netty documentation on Channelgroup explanation:

A Thread-safe Set, contains open Channels and provides various bulk operations on them. Using Channelgroup, you can categorize Channels to a meaningful group (e.g. on a per-service or per-state basis.) A closed Channel is automatically removed from the collection and so then you don ' t need to worry about the life cycle of the Added Channel. A Channel can belong to more than one channelgroup.

When a new client connects to the server, the corresponding channel is added to a channelgroup, and when the publisher publishes the message, the server can write the message through Channelgroup to all clients.

public class TCPServer {public static void main (string[] args) throws Interruptedexception {Eventloopgroup Bossgroup = new Nioeventloopgroup (); Eventloopgroup Workergroup = new Nioeventloopgroup (); try {serverbootstrap b = new Serverbootstrap (); B.group (BossGroup, Workergroup). Channel (Nioserversocketchannel.class). Childhandler (New channelinitializer<socketchannel> () {@ overridepublic void Initchannel (Socketchannel ch) throws Exception {Channelpipeline pipeline = Ch.pipeline (); Pipeline.addlast (new Linebasedframedecoder);p ipeline.addlast (New Stringdecoder (Charsetutil.utf_8)); Pipeline.addlast (New Stringencoder (charsetutil.utf_8));p ipeline.addlast (New Tcpserverhandler ());}); Channelfuture f = b.bind (8080). sync (); F.channel (). Closefuture (). sync (); finally {workergroup.shutdowngracefully (); bossgroup.shutdowngracefully ();}}} Class Tcpserverhandler extends Channelinboundhandleradapter {//Channelgroup is used to save all connected clients, Note To use static to guarantee that there is only one channelgroup instance, otherwise each new tcpserverhandler will create a CHANNELGROUPPRIvate static Channelgroup channels = new Defaultchannelgroup (globaleventexecutor.instance); @Overridepublic void Channelactive (Channelhandlercontext ctx) {Channels.add (Ctx.channel ());//Add new connections to Channelgroup, When the connection is broken Channelgroup automatically removes the corresponding channel} @Overridepublic void Channelread (Channelhandlercontext ctx, Object msg) { Channels.writeandflush (msg + "\ r \ n"); After receiving the message, send the message to all clients in Channelgroup} @Overridepublic void Exceptioncaught (Channelhandlercontext ctx, throwable cause)  {//Cause.printstacktrace (); Temporarily print out the exception, because Publishclient will immediately disconnect after publishing a message, and the server will send a message to publishclient, so it throws an exception ctx.close ();}}

Twisted:

In twisted, global data is typically placed in factory, and each connection-related data is placed in protocol. So here you can add a property to the factory to hold the Protocol collection, representing all the clients that connect to the server. When a new client connects to the server, the corresponding protocol instance is placed in the collection, and the corresponding protocol is removed from the collection when the connection is broken. When the server receives a message published by the publisher, it traverses all the clients and sends a message.

#-*-coding:utf-8–*-from twisted.protocols.basic import lineonlyreceiverfrom twisted.internet.protocol Import Factoryfrom twisted.internet Import Reactorclass tcpserverhandle (lineonlyreceiver):     def __init__ (self, Factory):        self.factory = Factory    def connectionmade (self):        Self.factory.clients.add (self) # New connection add connection corresponding protocol instance to clients    def connectionlost (self, Reason):        self.factory.clients.remove (self) # The connection disconnects the protocol instance corresponding to the Remove connection    def linereceived (self, line):        # traverses all connections and sends data for the        C in self.factory.clients:            C.sendline (line) class Tcpserverfactory (Factory):    def __init__ (self):        self.clients = set () # The set collection is used to save all clients connected to the server    def buildprotocol (self, addr):        return Tcpserverhandle (self) reactor.listentcp (8080 , Tcpserverfactory ()) Reactor.run ()

The following are two client programs, one for publishing messages, and one for clients subscribing to messages.

The client that publishes the message is simple-write a message to the server:

public class Publishclient {public static void main (string[] args) throws IOException {socket socket = Null;outputstream O UT = null;try {socket = new socket ("localhost", 8080); out = Socket.getoutputstream (); Out.write ("hello\r\n". GetBytes ()); Publish information to server Out.flush ();} Finally {//close connection out.close (); Socket.close ();}}}

When a client that subscribes to a message connects to the server, it blocks the publication message waiting for the receiving server to send:

public class Subscribeclient {public static void main (string[] args) throws IOException {socket socket = NULL; BufferedReader in = null;try {socket = new socket ("localhost", 8080) and in = new BufferedReader (new InputStreamReader (socket). getInputStream ()); (true) {String line = In.readline ();//block waiting for server to publish message System.out.println (line);}} Finally {//close connection in.close (); Socket.close ();}}}

Test for Mina, Netty, Twisted servers, respectively:

1, first open the server when testing;
2, and then run the subscription message client subscribeclient,subscribeclient can open more than one;
3. Finally, the client publishclient that runs the release message can run multiple times to see the output of all subscribeclient.

The result can be found that when the client running the publishing message Publishclient publishes a message to the server, the server proactively forwards the message to all TCP connections, and all client subscribeclient that subscribe to the message receive the message and print it out.


Fork Brother reproduced please indicate the source: http://blog.csdn.net/xiao__gui/article/details/39396789



Mina, Netty, twisted Together (vii): Publish/Subscribe (publish/subscribe)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.