对Spray-can 启动http server的理解

对IO(Http) ? Http.Bind(service, interface = “localhost”, port = 8080)的理解

先上代码,主启动程序及发送Http.Bind的类,放在文件Boo.scala中,与原官方的standalone例子相比,这个是稍微进行了修改。

package com.example

import akka.actor.{ActorRef, Actor, ActorSystem, Props}
import akka.io.{Tcp, IO}
import spray.can.Http
import akka.pattern.ask
import akka.util.Timeout
import scala.concurrent.duration._

object Boot extends App{

  // we need an ActorSystem to host our application in
  implicit val system = ActorSystem("on-spray-can")

  // create and start our service actor
  val service = system.actorOf(Props[MyServiceActor], "demo-service")

  val server = system.actorOf(Props(new Server(service,system)), "demo-server")
}

class Server(service:ActorRef,implicit val  system:ActorSystem) extends Actor{
  implicit val timeout = Timeout(5.seconds)
  IO(Http) ! Http.Bind(service, interface = "localhost", port = 8088)

  def receive = {
    case x:Tcp.Bound => println("Tcp.Bound="+x)
    case x => println("other messages : "+x)
  }
}

MyServiceActor这个类放在这里

IO(Http)返回一个ActorRef变量,在spray.can.Http中实现, 实际上源代码如下

    val manager = manager = system.actorOf(
    props = Props(new HttpManager(Settings)) withDispatcher Settings.ManagerDispatcher,
    name = "IO-HTTP")
  所以IO(Http)返回的就是这个manager。而这个manager就是在上面代码创建的HttpManager实例。

当这个manager接收到 Http.Bind消息时,就会根据Bind内容及配置创建一个实例去监听端口。代码在spray.can中实现HttpManager的部分。如下

case bind: Http.Bind =>
      val commander = sender()
      listeners :+= context.watch {
        context.actorOf(
          props = Props(newHttpListener(commander, bind, httpSettings)) withDispatcher ListenerDispatcher,
          name = "listener-" + listenerCounter.next())
      }

   这时HttpManager便启动了一个HttpListener实例去监听tcp端口,如果这个HttpListener实例成功绑定了tcp端口,则HttpListener会收到Tcp.Bound消息,这个Tcp.Bound消息也将会发送给上述代码中的server。注意这个Tcp.Bound消息在程序 整个运行过程中只会出现一次。除非你多次向IO(Http)发送Http.Bind消息。
    此时HttpListener实例其实就是一直在监听tcp/ip层的数据, 当外部向服务器进行请求时,HttpListener实例首先会收到一个Tcp.Connected消息,然后马上创建HttpServerConnection实例,这个HttpServerConnection会将tcp层的消息封装成http层的消息。然后再发送给Http.Bind(service, interface = "localhost", port = 8080)中的service。这时service收到的消息其实已经是封闭好了的HttpRequest消息。
      整个过程就是首先创建HttpManager,即IO(Http),然后向这个manager发送Http.Bind消息,创建HttpListener监听tcp层数据,一有外部连接,马上创建HttpServerConnection,该HttpServerConnection会将tcp层的数据进行封装,再以HttpRequest的形式传送给上层应用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
android上怎样让一个Service开机自动启动 Posted on 2009-02-08 21:55 hk_king 阅读(168) 评论(0) 编辑 收藏 网摘 所属分类: 移动开发 转载出处:http://www.androidlab.cn/viewthread.php?tid=421&extra=page%3D1 1.首先开机启动后系统会发出一个Standard Broadcast Action,名字叫android.intent.action.BOOT_COMPLETED,这个Action只会发出一次。 2.构造一个IntentReceiver类,重构其抽象方法onReceiveIntent(Context context, Intent intent),在其中启动你想要启动的Service。 3.在AndroidManifest.xml中,首先加入<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>来获得BOOT_COMPLETED的使用许可,然后注册前面重构的IntentReceiver类,在其<intent-filter>中加入<action android:name="android.intent.action.BOOT_COMPLETED" /> ,以使其能捕捉到这个Action。 一个例子 xml: <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission> <receiver android:name=".OlympicsReceiver" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </receiver> java: public class OlympicsReceiver extends IntentReceiver { /*要接收的intent源*/ static final String ACTION = "android.intent.action.BOOT_COMPLETED"; public void onReceiveIntent(Context context, Intent intent) { if (intent.getAction().equals(ACTION)) { context.startService(new Intent(context, OlympicsService.class), null);//启动倒计时服务 Toast.makeText(context, "OlympicsReminder service has started!", Toast.LENGTH_LONG).show(); } } } 注意:现在的IntentReceiver已经变为BroadcastReceiver,OnReceiveIntent为onReceive。所以java这边的代码为: (也可以实现应用程序开机自动启动) public class OlympicsReceiver extends BroadcastReceiver { /*要接收的intent源*/ static final String ACTION = "android.intent.action.BOOT_COMPLETED"; public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(ACTION)) { context.startService(new Intent(context, OlympicsService.class), null);//启动倒计时服务 Toast.makeText(context, "OlympicsReminder service has started!", Toast.LENGTH_LONG).show(); //这边可以添加开机自动启动的应用程序代码 } } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值