Git Product home page Git Product logo

chatbox's Introduction

ChatBox

Simple Chat System Using Akka Actors (Akka Remoting)

ChatBox Actor

Manages the Client Actors and Client Actors register with the ChatBox Actor. The IP of the ChatBox actor is available to Client Actors. ChatBox actor watches each Client actor that registers itself with it and removes them from the list of users once Client actors are unreachable.

Conf for ChatBoxActor

application.conf


    akka {
      loglevel = "INFO"
      actor {
        provider = "akka.remote.RemoteActorRefProvider"
      }
      remote {
        enabled-transports = ["akka.remote.netty.tcp"]
        netty.tcp {
          hostname = "127.0.0.1"
          port = 2222
        }
        log-sent-messages = on
        log-received-messages = on
      }
    }
    

ChatBox.scala

    package actors
    
    import akka.actor.{Terminated, ActorRef, ActorLogging, Actor}
    
    /**
     * Created by android on 21/3/15.
     */
    
    object ChatBox {
      case class Register(name: String)
      case class Message(from: String, to: String, body: String)
    }
    
    class ChatBox extends Actor with ActorLogging {
    
      var clients = Map.empty[String, ActorRef]
    
      import ChatBox._
      import Client._
    
      override def receive = {
        case Register(name) => {
         if (! (clients contains name) ) {
           clients += (name -> sender)
           context watch sender
           log.info("Clients")
           log.info(clients.mkString("\n"))
         }
        }
    
        case Message(from, to, body) =>
          log.info(s"from: $from says: $body to: $to")
          if(clients contains to) {
            clients(to) ! ReceiveMessage(from, body)
          }else {
            log.info("message dropped")
          }
    
        case Terminated(actor) => {
          clients = clients.filter(_._2 != actor)
        }
        case _ => log.info("unknown message")
      }
    }
    

Client Actor

Each Client Actor represents the User and registers with the ChatBox Actor initially. Registration happens by first looking up the actor using context.actorSelection("akka.tcp://ChatSystem@someip:port/user/ChatBox") and then the Register message is sent by the client to the ChatBox actor thus registering with the chatbox actor.

Conf for ClientActor

client.conf


    akka {
      loglevel = "INFO"
      actor {
        provider = "akka.remote.RemoteActorRefProvider"
      }
      remote {
        enabled-transports = ["akka.remote.netty.tcp"]
        netty.tcp {
          hostname = "127.0.0.1"
          port = 0
        }
        log-sent-messages = on
        log-received-messages = on
      }
    }
    

Client.scala

    
    package actors
    
    import akka.actor.{ActorLogging, ActorSelection, Actor}
    
    /**
     * Created by android on 21/3/15.
     */
    object Client {
      case class SendMessage(to: String, message: String)
      case class ReceiveMessage(from: String, message: String)
    }
    
    class Client(name: String, ip: String) extends Actor with ActorLogging {
    
      import ChatBox._
      import Client._
    
      var chatBox: Option[ActorSelection] = None
    
      override def preStart(): Unit = {
        chatBox = Some(context.actorSelection("akka.tcp://ChatSystem@$ip:2222/" +
          "user/ChatBox")) // node that chat box actor lookup is done using ChatBoxActor Running machine IP.
          //localhost if both ChatBoxActor and Client Actor are running on same machine.
    
        chatBox.map(actor => actor ! Register(name))
    
        chatBox.getOrElse({
          println("ChatBox unreachable, shutting down :(")
          context.stop(self)
        })
      }
    
      override def receive = {
        case SendMessage(to, message) => chatBox.map(actor => actor ! Message(name, to, message))
        case ReceiveMessage(from, message) =>
          println(s"$from says: $message")
        case _ => log.info("unknown message")
      }
    }

Main

Start ChatBox first on a Machine and use the IP of the ChatBox to lookup ChatBox from Client

StartChatBox

    package main
    
    import actors.ChatBox
    import akka.actor.{Props, ActorSystem}
    import com.typesafe.config.ConfigFactory
    
    /**
     * Created by android on 21/3/15.
     */
    object StartChatBox {
      def main(args: Array[String]): Unit = {
        val config = ConfigFactory.load()
        val chatSystem = ActorSystem("ChatSystem", config)
        val chatBox = chatSystem.actorOf(Props[ChatBox], name = "ChatBox")
      }
    }

StartClient

    
    package main

    import actors.Client
    import akka.actor.{Props, ActorSystem}
    import com.typesafe.config.ConfigFactory

    /**
     * Created by android on 21/3/15.
     */
    object StartClient {
      def main(args: Array[String]): Unit = {
        if (args.isEmpty) {
          println("Please provide IP of ChatBox Actor as the commandline argument")
          System.exit(0)
        }
        val config = ConfigFactory.load("client")
        val clientSystem = ActorSystem("ClientSystem", config)
        println("Enter your Nick Name:")
        var name = Console.readLine.trim
        while (name == "") {
          println("Enter your Nick Name:")
          name = Console.readLine.trim
        }
        val client = clientSystem.actorOf(Props(new Client(name)), "Client")

        println("Type message end with -> after -> type name of the person to send " +
          "and hit enter to send messages")

        while (true) {
          val line = Console.readLine.trim
          if (line != "" && line.contains("->") && line.split("->").size == 2) {
            val texts = line.split("->")
            client ! Client.SendMessage(texts(1).trim, texts(0).trim)
          }
        }
      }
    }
    

Usage

Start ChatBox Actor

sbt "runMain main.StartChatBox" //note the IP of the machine

now Start Client Actor

sbt "runMain main.StartClient 127.0.0.1" // IP of the machine running chatbox actor

chatbox's People

Contributors

pamu avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar

Forkers

capesepias

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.