Ruby on rails 从iOS应用程序连接到ActionCable

Ruby on rails 从iOS应用程序连接到ActionCable,ruby-on-rails,websocket,ruby-on-rails-5,actioncable,Ruby On Rails,Websocket,Ruby On Rails 5,Actioncable,我一整天都在忙这个。我有一个非常简单的ActionCable示例应用程序(聊天应用程序),由David Heinemeier Hansson开发,工作正常() 我正在尝试用iPhone应用程序连接websocket。当我连接到ws://localhost:3000/cable时,我能够接收ping,但我不太确定如何从javascript上下文外部订阅频道。//首先打开套接字连接 var ws = new WebSocket("ws://localhost:3000/cable"); //订

我一整天都在忙这个。我有一个非常简单的ActionCable示例应用程序(聊天应用程序),由David Heinemeier Hansson开发,工作正常()


我正在尝试用iPhone应用程序连接websocket。当我连接到
ws://localhost:3000/cable
时,我能够接收ping,但我不太确定如何从javascript上下文外部订阅频道。

//首先打开套接字连接

var ws = new WebSocket("ws://localhost:3000/cable");  
//订阅频道
//“i”应该是json格式

var i = { 'command': 'subscribe', 'identifier': {'channel':'ProfileChannel', 'Param_1': 'Value_1',...}};

 ws.send(i);
//之后,您将在“onmessage”函数中接收数据


干杯

哦,老兄,我读了这个问题后也遇到了这个问题

过了一会儿,我终于找到了这个神奇的Github问题页面:

我知道这个补丁会破坏一些测试。那不是 我很惊讶。但我认为最初的问题仍然相关 不应该关门

发送到服务器的以下JSON应成功:

{“命令”:“订阅”,“标识符”:{“频道”:“变更频道”}

它没有!您必须发送以下邮件:

{“命令”: “订阅”,“标识符”:“{\”频道\“:\”更改频道\“}”

根据Github用户关于Rails问题的建议,我终于让iOS应用程序订阅了room频道

我的设置如下:

  • 目标C
  • 使用PocketSocket框架进行web套接字连接
  • 轨道5 RC1
  • Ruby 2.2.4p230
我想你知道如何使用CoCoapod安装PocketSocket

相关代码如下:

ViewController.h 重要提示: 我还深入研究了subscription类的源代码:

def add(data)
        id_key = data['identifier']
        id_options = ActiveSupport::JSON.decode(id_key).with_indifferent_access

        subscription_klass = connection.server.channel_classes[id_options[:channel]]

        if subscription_klass
          subscriptions[id_key] ||= subscription_klass.new(connection, id_key, id_options)
        else
          logger.error "Subscription class not found (#{data.inspect})"
        end
      end
注意这一行:

connection.server.channel_classes[id_options[:channel]]
我们需要为通道使用类的名称

DHH youtube视频使用“room_channel”作为房间名称,但该频道的类文件名为“RoomChannel”

我们需要使用通道的类名而不是实例名

发送消息 为了防止其他人也想知道如何发送消息,以下是我向服务器发送消息的iOS代码:

-(void)sendMessage:(NSString *)message
{
    NSString *strMessage = [[NSString alloc] initWithFormat:@"{ \"action\": \"speak\", \"message\": \"%@\" }", message];

    NSString *strChannel = @"{ \"channel\": \"RoomChannel\" }";

    id data = @{
                @"command": @"message",
                @"identifier": strChannel,
                @"data": strMessage
                };

    NSData * jsonData = [NSJSONSerialization  dataWithJSONObject:data options:0 error:nil];
    NSString * myString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

    NSLog(@"myString= %@", myString);

    [self.socket send:myString];
}
这假设您已经连接了UITextField来处理按返回键或UI上的某个“发送”按钮

这整个演示应用程序是一个快速的黑客,显然,如果我在一个真正的应用程序中这样做,我会使我的代码更干净,更可重用,并将其抽象成一个类

从真正的iPhone设备连接到Rails服务器: 为了让iPhone应用程序在真实的设备上与Rails服务器对话,而不是在iPhone模拟器上

请执行以下操作:

  • 检查计算机的TCP/IP地址。例如,在我的iMac上,某些天可能是10.1.1.10(如果使用DHCP,将来会自动更改)
  • 编辑Rail的
    config>environment>development.rb
    文件,并将其放在
    end
    关键字前面的某个位置:

    Rails.application.config.action\u cable.allowed\u request\u origins=['http://10.1.1.10:3000']

  • 使用以下命令启动Rails服务器:

    rails服务器-b0.0.0.0

  • 在iPhone设备上构建并运行iPhone应用程序。您现在应该能够连接并发送消息:D

  • 我从以下链接获得了这些解决方案:


    希望这对以后的其他人有所帮助。

    实际上,这是我用来连接action cable的代码片段

      function WebSocketTest()
       {
             var ws = new WebSocket("ws://localhost:3000/cable");
             ws.onopen = function(data)
             {
               var i = JSON.stringify({"command":"subscribe" , "identifier": JSON.stringify({"channel":"CHANNEL_NAME"})});
               // send data request
               var j =  JSON.stringify({"command":"message","identifier": JSON.stringify({"channel":"CHANNEL_NAME"}),"data": {"message":"Hello World","action": "METHOD_NAME_IN_CHANNEL","email": "abc@xyz.com",  "token" : "xxxxxxxxxxxxx", "id": {"id_message" : "something", "ddd" : "something"}}}) 
               var response = ws.send(i);
                setTimeout(function()
                {
                  var response1 = ws.send(j);
                }, 1000);
             };
             ws.onmessage = function (evt) 
             { 
                var received_msg = evt.data;
             };
          }
    

    我也试着这么做,但没有成功。你在客户端IOS部分使用了哪些代码?你知道吗?这是Javascript还是WebSocket来自哪个库?你能分享你的路由吗?你好。我试过了,但没有收到广播,这里是我的JS``ws.onopen=(data)=>{const I=JSON.stringify({command:'subscribe',identifier:JSON.stringify({channel:'polls_channel'});//发送数据请求const response=ws.send(I);//eslint disable line};ws.onmessage=((message)=>{if(JSON.parse(message.data).type==='change'){fetchPolls();}})```要显示接收数据,请使用以下代码ws.onmessage=function(evt){var received_msg=evt.data;var json_obj=json.parse(received_msg);console.log(“Rcvd”,json_obj[“message”]);解除这些订阅有什么考虑因素吗?如果我想断开连接,我可以简单地断开连接,还是需要发送ActionCable消息来正确清理此连接?
    -(void)sendMessage:(NSString *)message
    {
        NSString *strMessage = [[NSString alloc] initWithFormat:@"{ \"action\": \"speak\", \"message\": \"%@\" }", message];
    
        NSString *strChannel = @"{ \"channel\": \"RoomChannel\" }";
    
        id data = @{
                    @"command": @"message",
                    @"identifier": strChannel,
                    @"data": strMessage
                    };
    
        NSData * jsonData = [NSJSONSerialization  dataWithJSONObject:data options:0 error:nil];
        NSString * myString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    
        NSLog(@"myString= %@", myString);
    
        [self.socket send:myString];
    }
    
      function WebSocketTest()
       {
             var ws = new WebSocket("ws://localhost:3000/cable");
             ws.onopen = function(data)
             {
               var i = JSON.stringify({"command":"subscribe" , "identifier": JSON.stringify({"channel":"CHANNEL_NAME"})});
               // send data request
               var j =  JSON.stringify({"command":"message","identifier": JSON.stringify({"channel":"CHANNEL_NAME"}),"data": {"message":"Hello World","action": "METHOD_NAME_IN_CHANNEL","email": "abc@xyz.com",  "token" : "xxxxxxxxxxxxx", "id": {"id_message" : "something", "ddd" : "something"}}}) 
               var response = ws.send(i);
                setTimeout(function()
                {
                  var response1 = ws.send(j);
                }, 1000);
             };
             ws.onmessage = function (evt) 
             { 
                var received_msg = evt.data;
             };
          }