2013-03-12 81 views
9

我使用我的Android应用程序的谷歌云端通讯(GCM)服务。我已经按照所有规则实施了它,并且工作正常。好吧,差不多。发送GCM消息(服务器端)经常会失败 - 但远总是

大多数情况下,我在的情况下,60-70%的人说,我可以成功地从我的服务器发送GCM消息,使用web服务对谷歌的网页所讨论的。

通常情况下,我从web服务,这表明我成功发送的GCM消息答复如下:

{ 
    "multicast_id":8378088572050307085, 
    "success":1, 
    "failure":0, 
    "canonical_ids":0, 
    "results": 
    [ 
     { 
      "message_id":"0:1363080282442710%7c4250c100000031" 
     } 
    ] 
} 

这话说:一切OK,消息中发送。

然而,在许多情况下,我调用webservice时得到一个HTTP错误,上面写着:

无法读取传输连接的数据:已建立 连接被软件在主机中止。

这是.NET消息告诉我调用Web服务(使用HttpWebRequest和POST)失败。

这是一些日志信息,显示的问题:

enter image description here

这是我使用的用于调用WS代码:

public static string SendMessage(string registrationId, string command, string extra, bool retry) 
{ 
    try 
    { 
     HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://android.googleapis.com/gcm/send"); 
     request.Method = PostWebRequest; 
     request.KeepAlive = false; 

     GCMPostPacket json = new GCMPostPacket() 
     { 
      collapse_key = "1", 
      time_to_live = 60, 
      registration_ids = new List<string>(new string[] { registrationId }), 
      data = new GcmData() 
      { 
       message = command, 
       misc = extra 
      } 
     }; 
     // Converting to JSON string 
     string jsonString = SICJsonProtocol.JSONHelper.Serialize<GCMPostPacket>(json); 
     byte[] byteArray = Encoding.UTF8.GetBytes(jsonString); 

     request.ContentType = "application/json"; 
     request.ContentLength = byteArray.Length; 
     request.ProtocolVersion = HttpVersion.Version10; 

     request.Headers.Add(HttpRequestHeader.Authorization, "key=" + "MyVerySecretKey"); 

     Stream dataStream = request.GetRequestStream(); 
     dataStream.Write(byteArray, 0, byteArray.Length); 
     dataStream.Close(); 

     using (WebResponse response = request.GetResponse()) 
     { 
      HttpStatusCode responseCode = ((HttpWebResponse)response).StatusCode; 
      if (responseCode.Equals(HttpStatusCode.Unauthorized) || responseCode.Equals(HttpStatusCode.Forbidden)) 
      { 
       Console.WriteLine("Unauthorized - need new token"); 
      } 
      else if (!responseCode.Equals(HttpStatusCode.OK)) 
      { 
       Console.WriteLine("Response from web service not OK :"); 
       Console.WriteLine(((HttpWebResponse)response).StatusDescription); 
      } 

      StreamReader reader = new StreamReader(response.GetResponseStream()); 
      string responseLine = reader.ReadLine(); 
      Console.WriteLine("************************"); 
      Console.WriteLine("GCM send: " + responseCode + " | " + responseLine); 
      // This is the log shown in the image above 
      SRef.main.gui.ServiceUpdate("GCM send: " + responseCode + " | " + responseLine); 
      reader.Close(); 
      response.Close(); 
      return responseLine; 
     } 

    } 
    catch (Exception e) 
    { 
     // This is the log shown in the image above 
     SRef.main.gui.ServiceUpdate("Failed send GCM, " + (retry ? "retrying in 20 sec" : "not retrying") + ". Error=" + e.Message); 
     if (retry) 
     { 
      System.Threading.ThreadPool.QueueUserWorkItem(delegate(object obj) 
      { 
       try 
       { 
        System.Threading.Thread.Sleep(20000); 
        SendMessage(registrationId, command, extra, false); 
       } 
       catch (Exception ex) 
       { 
       } 
      }); 
     } 
     return null; 
    } 
} 

任何人都可以看到,如果我做的事情错误的,或者如果我缺少一些一般的东西?

+2

是否可以在外部catch-block内记录'e'的值?它可能包含有用的信息。 – Nachi 2013-03-19 14:03:55

+0

当然,我会补充一点,看看它是否有帮助 – Ted 2013-03-20 20:32:03

+0

其实,它已经在那里。 e.Message写在输出中,这就是你看到的错误信息...... * +“。Error =”+ e.Message); * – Ted 2013-03-20 21:14:43

回答

3

无法从传输连接读取数据:建立的连接被主机中的软件中止。

此错误无关,与特别GCM API。这意味着你的客户端试图联系Web服务但建立在网络层中的一个已经被切断了连接。根据你在哪里得到这个错误和错误信息,它可能意味着几件事情。

  1. 由于套接字超时,您的客户端决定中止连接。增加客户端读取/套接字超时以改善情况。

  2. 在客户端和服务器之间位于负载平衡器丢弃的连接。每一方都认为另一方放弃了这种联系。

网络超时通常是一个巨大的痛苦,因为它永远不会清楚连接丢失的位置以及丢弃的位置。如果增加超时无助于我建议通过可以嗅探HTTPS流量(charles/TCPMON)的代理发送请求,或使用Wireshark查看哪些数据包被丢弃。

您的Android应用程序还具有可在统计选项卡上启用的GCM监控功能。检查GCM API是否在该图上报告200 OK以外的状态消息。这将有助于进一步缩小问题范围。如果没有关于200以外的状态代码的报告,则表示GCM从未收到您的API请求。

+0

我知道它是一个网络问题,但它不是一般的网络问题,因为我我总是连接到互联网(否则我不会连接到外部世界等)。它在我的服务器和gcm-servers之间是特定的。如果我在另一台计算机上或本地运行它,这也是同样的问题。 – Ted 2013-03-20 20:34:16

+0

统计标签?这是哪里? – Ted 2013-03-20 20:34:42

+0

将[发件人ID在控制台上](http://support.google.com/googleplay/android-developer/answer/2663268?hl=en)链接后,您应该开始看到GCM响应代码状态。转到您的应用 - >统计信息 - >从下拉列表中选择GCM消息 - >点击'GCM响应代码'标签。 – 2013-03-21 04:20:58

相关问题