Ted*_*Ted 9 .net android http google-cloud-messaging
我正在为我的Android应用程序使用Google Cloud Messaging(GCM)服务.我已经按照所有规则实现了它,并且它有效.好吧,差不多.
大多数情况下,我会说在60-70%的情况下,我可以使用谷歌网页上讨论的网络服务从我的服务器成功发送GCM消息.
通常,我从webservice获得以下回复,表明我成功发送了GCM消息:
{
"multicast_id":8378088572050307085,
"success":1,
"failure":0,
"canonical_ids":0,
"results":
[
{
"message_id":"0:1363080282442710%7c4250c100000031"
}
]
}
Run Code Online (Sandbox Code Playgroud)
这就是说:一切OK,发送的消息.
但是,在许多情况下,我在调用Web服务时遇到HTTP错误,其中说:
无法从传输连接读取数据:已建立的连接已被主机中的软件中止.
这是.NET消息,告诉我调用webservice(使用HttpWebRequest和POST)失败.
这是一些显示问题的日志消息:

这是我用来调用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;
}
}
Run Code Online (Sandbox Code Playgroud)
任何人都可以看到我做错了什么,或者我是否遗漏了一般的东西?
无法从传输连接读取数据:已建立的连接被主机中的软件中止。
此错误与 GCM API 特别无关。这意味着您的客户端尝试联系 Web 服务,但所建立的连接已在网络层之一被切断。根据您收到此错误的位置和错误消息,它可能意味着多种含义。
由于套接字超时,您的客户端决定中止连接。增加客户端读/套接字超时来改善这种情况。
位于客户端和服务器之间的负载平衡器断开了连接。每一方都认为另一方断开了连接。
网络超时通常是一个巨大的痛苦,因为永远不清楚连接在哪里以及谁断开了。如果增加超时没有帮助,我建议通过可以嗅探 HTTPS 流量的代理发送请求(charles / TCPMON)或使用 Wireshark 来查看哪些数据包被丢弃。
您的 Android 应用程序还具有 GCM 监控功能,您可以在“统计信息”选项卡上启用它。检查 GCM API 是否在该图表上报告除 200 OK 之外的状态消息。这将有助于进一步缩小问题范围。如果除了 200 之外没有任何状态代码报告,则意味着 GCM 从未收到您的 API 请求。