2016-03-29 5 views
1

Я использую ScalaPB для моего компилятора protobuf, который генерирует классы case, парсеры и сериализаторы Scala для моих буферов протокола.Как отправлять и получать сообщения protobuf через Akka Tcp

У меня есть простой протокол protobuf в файле .proto, который был скомпилирован в класс Scala, благодаря ScalaPB.

option java_outer_classname = "MovementProtos"; 

message Move { 
    required string direction = 1; 
    required string mode = 2; 
} 

Этот файл компилируется и позволяет мне сделать что-то вроде:

val move = Move(direction = "up", mode = "walk") 

У меня есть обработку соединения TCP в Akka актер.

class PacketHandler extends Actor { 

    def receive: Receive = { 
    case m: Move => 
     // successfully matched against Move case class message 
    case Tcp.Received(data) => 
     // didn't match any messages 
    case _: Tcp.ConnectionClosed => 
     context.stop(self) 
    } 
} 

Если я отправить сообщение в Move Protobuf к моему PacketHandler, он будет успешно соответствовать против моего Move случае класса с тем, как я написал свой receive?

Как отправить сообщение Move protobuf? Скажем, когда он успешно совпадает с сообщением protobuf Move, он повторяет его.

def receive: Receive = { 
    case m: Move => 
    // successfully matched against Move case class message 
    // now echo back 'm' over the wire 
    sender ! Tcp.Write(???) 
    ... 
} 

У меня нет клиента, чтобы проверить мой PacketHandler актер, поэтому я использую телнет.

Также было бы полезно узнать, как выглядит кодированное сообщение Move, чтобы я мог создать свое соединение по telnet и отправить закодированное сообщение по проводу и проверить, будет ли оно декодироваться, когда оно достигнет PacketHandler.

ответ

1

Один из способов - отправить экземпляры в виде сообщений Akka. то есть. sender ! Tcp.Write(m). Экземпляры отправляются со всеми бинарными служебными данными класса Scala. Но такого рода поражает смысл использования буферов протокола.

Полоса пропускания, как правило, является одним из самых коротких/самых медленных ресурсов в системе, поэтому обычно вы используете функции сериализации и десериализации protobuf для rpc. Сериализуйте с помощью любой из функций to~ (то есть toByteString) и десериализуйте с помощью parseFrom.

+0

К сожалению, отправка классов классов Scala для меня не является выбором ... Сериализация с использованием toByteString - это то, что я искал в плане отправки закодированных данных. Смогу ли я сопоставлять с входящими сообщениями? Например, parseFrom ожидает десериализацию заданного определенного типа. Что, если я не обязательно знаю, какой тип сообщения проходит? –

+0

У вас должна быть одна конечная точка с URI для каждого типа сообщения. В противном случае вы можете обернуть каждое сообщение родительским сообщением (общим типом), которое указывает тип сообщения в строке и фактическое сообщение в байтовом поле, а ваша отдельная конечная точка десериализует родительское сообщение и затем десериализует завернутое сообщение на основе строка типа сообщения. protobuf автоматически не определяет тип сообщения. – kliew

+0

Спасибо! Это решение отлично поработало. –