为什么使用TcpClient发送Apple推送通知和Android导致应用程序挂起?

时间:2017-11-09 08:16:21

标签: c# push-notification tcpclient

我在网上搜索过,找不到解决问题的方法。

我有一个针对.net Framework 4.0的项目。

我有两种方法。一个用于将通知推送到ios设备,另一个用于将通知推送到Android设备。

这是我的第一个方法:

public void SendAplePushNotificationMessage(string body, int Participant_ID, int Trainer_ID)
    {
        var componentSetup = new ComponentSetup();
        var odsDevicesToken = componentSetup.getDevicesToken(Participant_ID, Trainer_ID, 1);
        if (odsDevicesToken.Tables[0].Rows.Count > 0)
        {
            foreach (DataRow dr in odsDevicesToken.Tables[0].Rows)
            {
                try
                {
                    var deviceToken = HexStringToByteArray(dr["DeviceToken"].ToString());
                    var memoryStream = new MemoryStream();
                    var writer = new BinaryWriter(memoryStream);
                    writer.Write((byte)0);  //The command
                    writer.Write((byte)0);  //The first byte of the deviceId length (big-endian first byte)
                    writer.Write((byte)32); //The deviceId length (big-endian second byte)
                    writer.Write(deviceToken);
                    writer.Write((byte)0); //First byte of payload length; (big-endian first byte)     
                    var payload = "{\"aps\":{\"alert\":\"" + body + "\",\"badge\":1,\"sound\":\"default\"}}";
                    var b1 = Encoding.UTF8.GetBytes(payload);
                    if (b1.Length > 256)
                    {
                        body = body.Substring(0, 106) + "...";
                        payload = "{\"aps\":{\"alert\":\"" + body + "\",\"badge\":1,\"sound\":\"default\"}}";
                        b1 = Encoding.UTF8.GetBytes(payload);
                    }
                    writer.Write((byte)b1.Length);
                    writer.Write(b1);
                    writer.Flush();
                    var array = memoryStream.ToArray();
                    memoryStream.Write(Encoding.ASCII.GetBytes(body), 0, body.Length);
                    var port = Convert.ToInt32(ConfigurationManager.AppSettings["APNPortNo"]);
                    var hostname = ConfigurationManager.AppSettings["APNHostName"];
                    var certificatePath = Server.MapPath("~") + ConfigurationManager.AppSettings["APNCertificatePath"].Replace("/", "\\");
                    Logger.LogInfoMessage("certificatePath: " + certificatePath);
                    var clientCertificate = new X509Certificate2(File.ReadAllBytes(certificatePath), "");
                    var certificatesCollection = new X509Certificate2Collection(clientCertificate);
                    var client = new TcpClient(hostname, port);
                    var sslStream = new SslStream(client.GetStream(), false,
                    new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
                    try
                    {
                        sslStream.AuthenticateAsClient(hostname, certificatesCollection, SslProtocols.Tls, false);
                        sslStream.Write(array);
                        sslStream.Flush();
                        client.Close();
                    }
                    catch (AuthenticationException ex)
                    {
                        client.Close();
                        var setupObj = new ComponentSetup();
                        setupObj.AddErrorLog(ex.Message, CamelRaceContext.UserSettings.User.USER_NAME, null,
                            Participant_ID, dr["DeviceToken"].ToString());
                        if (ex.InnerException != null)
                            Logger.LogErrorMessage(ex.InnerException, ex.InnerException.Message);
                        throw new CamelRaceApplicationException<MobileAdmin_ManageNotifications>(ex.Message, ex);
                    }
                    catch (CamelRaceApplicationException<MobileAdmin_ManageNotifications> ex)
                    {
                        throw new CamelRaceApplicationException<MobileAdmin_ManageNotifications>(ex.Message,ex);
                    }
                    catch (Exception e)
                    {
                        client.Close();
                        var setupObj = new ComponentSetup();
                        setupObj.AddErrorLog(e.Message, CamelRaceContext.UserSettings.User.USER_NAME, null, Participant_ID, dr["DeviceToken"].ToString());
                    }
                }
                catch (CamelRaceApplicationException<MobileAdmin_ManageNotifications> ex)
                {
                    throw new CamelRaceApplicationException<MobileAdmin_ManageNotifications>(ex.Message, ex);
                }
                catch (Exception exMain)
                {
                    var setupObj = new ComponentSetup();
                    setupObj.AddErrorLog(exMain.Message, CamelRaceContext.UserSettings.User.USER_NAME, null, Participant_ID, dr["DeviceToken"].ToString());
                    if (exMain.InnerException != null)
                        Logger.LogErrorMessage(exMain.InnerException, exMain.InnerException.Message);
                }
            }
        }
    }

第二种方法是:

private  void SendGCMPushNotificationMessage(string body, int Participant_ID, int Trainer_ID)
    {
        var _ComponentSetup = new ComponentSetup();
        var odsDevicesToken = _ComponentSetup.getDevicesToken(Participant_ID, Trainer_ID , 2);
        if (odsDevicesToken.Tables[0].Rows.Count > 0)
        {
            var registration_ids = new string[odsDevicesToken.Tables[0].Rows.Count];
            var index = 0;
            foreach (DataRow dr in odsDevicesToken.Tables[0].Rows)
            {
                registration_ids[index] = dr["DeviceToken"].ToString();
                index = index + 1;
            }
            if (registration_ids.Length > 0)
            {
                var GcmHttpUrl = ConfigurationManager.AppSettings["GcmHttpUrl"];
                var GcmApiKey = ConfigurationManager.AppSettings["GcmApiKey"];
                var notificationData = new JObject(
                    new JProperty("registration_ids", new JArray(registration_ids)),
                    new JProperty("notification", new JObject(
                    new JProperty("title", ConfigurationManager.AppSettings["title"]),
                    new JProperty("body", body),
                    new JProperty("icon", "myicon"),
                    new JProperty("sound", "default")
                    )),
                      new JProperty("data", new JObject(
                    new JProperty("state", ConfigurationManager.AppSettings["state"])
                    )
                    )

                );
                var contentText = notificationData.ToString(Formatting.None);
                var content = Encoding.UTF8.GetBytes(contentText);
                try
                {
                    var req = (HttpWebRequest)WebRequest.Create(GcmHttpUrl);
                    req.Method = "POST";
                    // Disable expect-100 to improve latency
                    req.ServicePoint.Expect100Continue = false;
                    req.ContentType = "application/json";
                    req.ContentLength = content.Length;
                    req.Headers.Add("Authorization", "key=" + GcmApiKey);
                    using (var s =req.GetRequestStream())
                    {
                        s.Write(content, 0, content.Length);
                        s.Close();
                    }
                    // Receive the HTTP response.
                    string response;
                    using (var res = (HttpWebResponse) req.GetResponse())
                    {
                        // Read the request body
                        using (TextReader r = new StreamReader(res.GetResponseStream(), Encoding.UTF8, true))
                        {
                            response = r.ReadToEnd();
                        }
                    }
                    Console.WriteLine("Response: " + response);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Exception: " + ex.ToString());
                    var setupObj = new ComponentSetup();
                    setupObj.AddErrorLog("Exception: " + ex.ToString(), CamelRaceContext.UserSettings.User.USER_NAME, null, Participant_ID,null);
                    if (ex is WebException)
                    {
                        var webex = (WebException)ex;
                        if (webex.Response != null)
                        {
                            var status = ((HttpWebResponse)webex.Response).StatusCode;

                            setupObj.AddErrorLog("Exception: " + status.ToString(), CamelRaceContext.UserSettings.User.USER_NAME, null, Participant_ID, null);
                            // Check the status code here...
                        }
                    }
                }
            }
        }
    }

现在,当设备数量为3或4时,此代码正常工作。

当这个数字增加时。像8423一样。

它会导致应用程序挂起。

目前我在按钮点击时调用此代码。

我想知道将使用任务类放置此代码会使其工作吗?

var task1 = Task.Factory.StartNew(() =>SendAplePushNotificationMessage(txtNotification.Text, Participant_ID, Trainer_ID) , TaskCreationOptions.LongRunning);

var task2 = Task.Factory.StartNew(() => SendGCMPushNotificationMessage(txtNotification.Text, Participant_ID, Trainer_ID), TaskCreationOptions.LongRunning);
                        Task.WaitAll(task1, task2);

我知道有些人会建议使用pushsharp。

我在考虑这样做。

然而推动锐利目标4.5。

我的项目目标4.0。

升级不是一种选择。

我的解决方案能否运作?

如果没有,那我怎么解决我的问题呢。

感谢。

0 个答案:

没有答案