为大量用户发送短信

时间:2013-05-09 11:40:30

标签: c# asp.net performance sms httpwebrequest

我想将SMS发送给大量用户(4000位用户),所以我将以下方法放在循环中:

protected int SendSMS(string url)
        {
            // Now to Send Data.

            StreamWriter writer = null;
            StringBuilder postData = new StringBuilder();
            Uri myUri = new Uri(url);
            postData.Append(HttpUtility.ParseQueryString(myUri.Query).Get("Username"));
            postData.Append(HttpUtility.ParseQueryString(myUri.Query).Get("Password"));
            postData.Append(HttpUtility.ParseQueryString(myUri.Query).Get("Sender"));
            postData.Append(HttpUtility.ParseQueryString(myUri.Query).Get("Recipients"));
            postData.Append(HttpUtility.ParseQueryString(myUri.Query).Get("MessageData"));



            string webpageContent = string.Empty;
            byte[] byteArray = Encoding.UTF8.GetBytes(postData.ToString());
            HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
            webRequest.Method = "POST";
            webRequest.ContentType = "application/x-www-form-urlencoded";
            webRequest.ContentLength = webRequest.ContentLength = byteArray.Length;

            writer = new StreamWriter(webRequest.GetRequestStream());


            try
            {
                using (Stream webpageStream = webRequest.GetRequestStream())
                {
                    webpageStream.Write(byteArray, 0, byteArray.Length);
                }

                using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
                {
                    using (StreamReader reader = new StreamReader(webResponse.GetResponseStream()))
                    {
                        webpageContent = reader.ReadToEnd();
                        //TODO:parse webpagecontent: iF response contains "OK"
                        if (webpageContent.Contains("OK")) return 1;
                        else return 0;
                    }
                }
                //return 1;

            }
            catch (Exception ee)
            {
                ErrMapping.WriteLog(url);
                string error = ee.Message + "<br><br>Stack Trace : " + ee.StackTrace;
                ErrMapping.WriteLog(error);
                return -1;
            }

        }

在特定数量的用户(例如65位用户)之后,其他用户未发送sms并且

我得到以下异常:

Error Message:Thread was being aborted.<br><br>Stack Trace :    at System.Net.UnsafeNclNativeMethods.OSSOCK.recv(IntPtr socketHandle, Byte* pinnedBuffer, Int32 len, SocketFlags socketFlags)
   at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, SocketError& errorCode)
   at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.PooledStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.Connection.SyncRead(HttpWebRequest request, Boolean userRetrievedStream, Boolean probeRead)
   at System.Net.ConnectStream.ProcessWriteCallDone(ConnectionReturnResult returnResult)
   at System.Net.HttpWebRequest.CheckDeferredCallDone(ConnectStream stream)
   at System.Net.HttpWebRequest.GetResponse()
   at SendSMS_EmailUI.Frm_SMS_send.SendSMS(String url) 

8 个答案:

答案 0 :(得分:6)

恕我直言,将代表申请进行的批量操作可以通过以下程序轻松完成

  1. 触发批量短信时,详细信息将输入数据库表格
  2. Windows服务将持续监控此表以获取任何更新
  3. 当Windows服务找到新条目时,它将只需几条记录,然后发送它们。批处理。
  4. 后续请求之间可能会有延迟。
  5. 这将确保您跟踪哪些订单项已失败,并且不会使用批量数据阻塞服务器。
  6. 这是最广泛建议的方法。

    请提供您对此实施的意见。

答案 1 :(得分:6)

我已经建立了一个短信门户网站。您所描述的内容在我的应用程序的v1.0中也经历过。解决方案是让我的SMS网关通过HTTP为我提供批量短信访问。我可以将最多1000个目的地放入XML(或逗号分隔)包并发送到批量SMS网关。因为我在共享主机上运行,​​所以我将其限制在500个目的地。

我有一个缓存/临时存储/表,在某些情况下我批量大目的地(最多1,000,000)和调度程序(基于计时器)每隔几秒发送每批500(通过重复调用脚本)直到消息发送。像魅力一样工作!

对于个性化消息,我鼓励客户端在转发到我的SMS门户之前使用我的桌面应用程序进行个性化。祝你好运

<强> PROCESS:

你需要三件物品

  1. 接收SendSMS请求的脚本
  2. 发送短信的脚本
  3. 调度程序/计时器(脚本/主机服务)
  4. 一个。发送短信请求到达

    a. The Message and Sender ID/ Sender GSM Number.
    
    b. The Destinations (as a comma delimited list). We'll assume 10,000 destinations
    

    B中。将目标分成500(您希望的任何大小),并在每个INBOX行/记录中记录500个目的地以及消息和SenderID。      注意:如果通过循环(10,000次循环)计算500次,则脚本可能会超时。我国的GSM号码是13位数。     所以我做了一个长度为500 (13 + 1)的循环子字符串,每批获得500个目的地(20个循环)。*

    ℃。调用发送短信的脚本。发送前500并将邮件标记为已发送。您可以添加发送时间。启动计划程序

    d。如果INBOX中存在任何未发送的消息并且发送它,则调度程序每1.5分钟检查一次。如果没有,Scheduler停止。     因此,在30分钟内发送10,000条消息

答案 2 :(得分:5)

我们做了类似于saravan为电子邮件建议的内容,并怀疑它可以正常工作。

基本上,在我们的Web服务器上运行的服务一次只发送x,并且每次发送之间都有自定义延迟y。 它可以在不到十分钟的时间内发送两千个,既没有CPU也没有带宽峰值。

我们原始设计中没有的一些提示要记住:

  1. 有办法手动停止所有发送(请参阅下一个提示)

  2. 以用户友好的方式终止特定邮件。如果您的代码(或用户)意外地发送了相同的内容五次,那么您需要一种方法来快速中止它。

  3. 对两个数字(上面的x&amp; y)使用配置文件,这样您无需重新部署即可进行调整。我认为y延迟是50毫秒。

  4. 在您决定将同一邮件捆绑到多个收件人之前,请确保智能手机无法回复其捆绑包中的其他所有人。

    HTH,

    -Chris C。

答案 3 :(得分:5)

我怀疑问题是因为你在asp.net网站上,这是一个长期运行的任务,它正在超时响应。

此超时在web.config中控制,默认设置为110秒。将此值增加到更长的数字,看看它是否开始工作。

  <system.web>
    <!-- 600 seconds = 10 minute timeout --->
    <httpRuntime executionTimeout="600"/>
  </system.web>

更好的方法是使用单独的线程并返回进度的更新 对用户来说,虽然这会更复杂,但最终更可靠。

请参阅Parallel.ForEach以了解此过程的简单方法。

Msdn - httpRuntime documention

答案 4 :(得分:5)

这不是回答您的原始问题,而是相关的有用信息。一旦你解决了这个问题,你可能会打另一个 - 电信公司通常会阻止批量发送的短信,以此来抑制短信垃圾邮件。如果您要在商业规模上这样做,您需要向移动营销协会提交一份简报,并获得他们的批准,这可能需要相当长的时间。

答案 5 :(得分:3)

检查您的StreamWriter是否已被处理

using (StreamWriter writer = new StreamWriter(webRequest.GetRequestStream()))
{

}

答案 6 :(得分:3)

可能是缓冲区值已满,请检查并将其置于web-config文件中的最大值

答案 7 :(得分:2)

也许你的网页请求速度过快:尝试放慢速度以排除时间问题,例如添加睡眠:

   System.Threading.Thread.Sleep(1000);

1000ms = 1秒只是一个提示,您应该尝试不同的值来查看是否有变化