필자는 영구적 인 소켓 연결에서 장기 실행 작업을 포함하는 액터에 상당한 문제가 있습니다. 다음은 4 개 미만의 서버 인스턴스를 만들면 올바르게 실행되는 테스트 코드입니다. 그러나 인스턴스를 더 만들면 다른 소켓이 시간 초과되기 때문에 항상 3 개 또는 4 개의 동시 소켓 연결로 끝납니다. 그 이유는 무엇이며 내 코드에 분명히 잘못된 것이 있는지 궁금합니다.스칼라 액터 : long running io operations
package test
import actors.Actor
import actors.Actor._
import java.io.{PrintStream, DataOutputStream, DataInputStream}
import java.net.{Socket, InetAddress}
import java.text.{SimpleDateFormat}
import java.util.{Calendar}
case class SInput(input: String)
case class SOutput(output: String)
case class SClose
case class SRepeat
import scala.xml._
class Config(xml: Node) {
var nick: String = (xml \ "nick").text
var realName: String = (xml \ "realName").text
var server: String = (xml \ "ip").text
var port: Int = (xml \ "port").text.toInt
var identPass: String = (xml \ "identPass").text
var joinChannels: List[String] = List.fromString((xml \ "join").text.trim, ' ')
}
object ServerStarter {
def main(args: Array[String]): Unit = {
var servers = List[Server]()
val a = actor {
loop {
receive {
case config: Config =>
actor {
val server = new Server(config)
servers = server :: servers
server.start
}
}
}
}
val xml = XML.loadFile("config.xml")
(xml \ "server").elements.foreach(config => a ! new Config(config))
}
}
class Server(config: Config) extends Actor {
private var auth = false
private val socket = new Socket(InetAddress.getByName(config.server), config.port)
private val out = new PrintStream(new DataOutputStream(socket.getOutputStream()))
private val in = new DataInputStream(socket.getInputStream())
def act = {
val _self = this
_self ! SRepeat
while (true) {
receive {
case SRepeat =>
try {
val input = in.readLine
if (input != null) {
actor {_self ! SInput(input)}
} else {
actor {_self ! SClose}
}
} catch {
case e: Exception =>
println(e)
actor {_self ! SClose}
}
case SClose =>
println(getDate + " closing: " + config.server + " mail: " + mailboxSize)
try {
socket.close
in.close
out.close
} catch {
case e: Exception =>
println(e)
}
case SInput(input: String) =>
println(getDate + " " + config.server + " IN => " + input + " mail: " + mailboxSize)
actor {onServerInput(_self, input)}
_self ! SRepeat
case SOutput(output: String) =>
println(getDate + " " + config.server + " OUT => " + output + " mail: " + mailboxSize)
actor {
out.println(output)
out.flush()
}
case x =>
println("unmatched: " + x + " mail: " + mailboxSize)
}
}
}
private def getDate = {
new SimpleDateFormat("hh:mm:ss").format(Calendar.getInstance().getTime());
}
def onServerInput(a: Actor, input: String) = {
if (!auth) {
authenticate(a)
}
else if (input.contains("MOTD")) {
identify(a)
join(a)
}
else if (input.contains("PING")) {
pong(a, input)
} else {
}
}
def authenticate(a: Actor) = {
a ! SOutput("NICK " + config.nick)
a ! SOutput("USER " + config.nick + " 0 0 : " + config.realName)
auth = true
}
def pong(a: Actor, input: String) = {
a ! SOutput("PONG " + input.split(":").last)
}
def identify(a: Actor) = {
if (config.identPass != "") {
a ! SOutput("nickserv :identify " + config.nick + " " + config.identPass)
}
}
def join(a: Actor) = {
config.joinChannels.foreach(channel => a ! SOutput("JOIN " + channel))
}
}
btw. 나는 2.7.6 결승 스칼라를 사용하고있다.
안녕하세요 최대, 오랜 시간을 보지 못했습니다! 당신이 scala에게 시험을하고 있다는 것을 알기 위해 차가워 요. –