有哪位高手了解美国发短信的服务接口

有谁了解美国发短信的服务接口
美国发短信的服务器有哪些?跟中国的短信猫一样的接口吗?是不是需要买相关的短信猫硬件?有谁了解的说一下。
还有 sms freeware是什么?

------解决方案--------------------
在中国买就可以,1百多吧,只是服务号不一样
C# code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SMSLibrary;
using System.IO.Ports;
using System.Text.RegularExpressions;
using System.IO;
using System.Threading;
using System.Diagnostics;

namespace SMSImpl {
    public class SMSModem {
        public bool IsOpen { get { return isOpen; } }
        public SMSModem(string portName) {
            this.portName = portName;

            Regex r1 = new Regex(@"^\+CMTI\:");
            Regex r2 = new Regex(@"^\+CMGR\:");
            Regex r3 = new Regex(@"^\+RING\:");

            ATBeginHandlerMap.Add(r1, OnBeginCMTI);
            ATBeginHandlerMap.Add(r2, OnBeginCMGR);
            ATBeginHandlerMap.Add(r3, OnBeginRING);

            ATHandlerMap.Add(r1, OnCMTI);
            ATHandlerMap.Add(r2, OnCMGR);
            ATHandlerMap.Add(r3, OnRING);

            responseMap.Add(typeof(SendSMSRequest), OnCMGSResponse);
        }

        public void Open() {
            port = new SerialPort(portName);
            port.Encoding = Encoding.Default;
            port.ReadTimeout = 30000;
            port.WriteTimeout = 30000;
            port.BaudRate = 9600;
            port.RtsEnable = true;

            port.Open();
            port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);

            AddRequestToQueue(new SettingReuqest("AT").Execute(port));
            Thread.Sleep(50);
            AddRequestToQueue(new SettingReuqest("ATE0").Execute(port));
            AddRequestToQueue(new SettingReuqest("AT+CMGF=1").Execute(port));
            AddRequestToQueue(new SettingReuqest("AT+CNMI=2,1").Execute(port));
            AddRequestToQueue(new SettingReuqest("AT+CSMP=49,167,0,8").Execute(port));

            isOpen = true;
        }

        public void Close() {
            port.DataReceived -= port_DataReceived;
            port.Close();
            isOpen = false;
        }

        public void Send(SMS arg) {
            if (arg.Text.Length > 70) {
                throw new Exception("短信超过70个字符!");
            }

            AddRequestToQueue(new SendSMSRequest(arg).Execute(port));
        }

        // ----------------------------------
        private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) {
            string line = string.Empty;

            try {
                while (port.BytesToRead > 0) {
                    line = port.ReadLine();
                    if (!string.IsNullOrEmpty(line) && "\r" != line) {
                        Console.WriteLine(line);
                        receiveBuffer.Add(line);

                        if (!isInterrupt) {
                            if (IsBeginInterrupt(line)) {
                                if (IsEndInterrupt()) {
                                    EndInterrupt();
                                }
                            } else {
                                string c = line.TrimEnd('\r');
                                if ("OK" == c || "ERROR" == c) {
                                    var response = new ModemResponse(receiveBuffer);
                                    response.Request = requestQueue.Dequeue();
                                    Type t = response.Request.GetType();
                                    if (responseMap.ContainsKey(t)) {
                                        responseMap[t](response);
                                    }
                                    receiveBuffer.Clear();
                                }
                            }
                        } else {
                            if (IsEndInterrupt()) {
                                EndInterrupt();
                            }
                        }
                    }
                }
            } catch (Exception ex) {
                Trace.WriteLine(ex);
            }
        }

        private void EndInterrupt() {
            interruptHandler(receiveBuffer);

            beginInterruptHandler = null;
            interruptHandler = null;
            receiveBuffer.Clear();
        }

        private bool IsEndInterrupt() {
            Trace.Assert(beginInterruptHandler != null);
            bool result = false;
            if (beginInterruptHandler(receiveBuffer)) {
                result = true;
            }
            return result;
        }

        private bool IsBeginInterrupt(string arg) {
            bool result = false;

            foreach (var each in ATBeginHandlerMap.Keys) {
                if (each.IsMatch(arg)) {
                    beginInterruptHandler = ATBeginHandlerMap[each];
                    interruptHandler = ATHandlerMap[each];
                    result = true;
                    break;
                }
            }

            return result;
        }

        private bool OnBeginCMTI(List<string> content) {
            return true;
        }

        private void OnCMTI(List<string> content) {
            // +CMTI:"SM",1
            Regex pattern = new Regex(@"^\+CMTI:.+,(\d+)");
            Match m = pattern.Match(content[0]);
            index = Convert.ToInt32(m.Groups[1].Value);

            AddRequestToQueue(new RetrieveSMSReuqest(index).Execute(port));
        }

        private bool OnBeginCMGR(List<string> content) {
            return (content.Count == 3);
        }

        private void OnCMGR(List<string> content) {
            Regex pattern = new Regex("^\\+CMGR:.+,\"(\\S+)\",");

            Match m = pattern.Match(content[0]);
            string address = m.Groups[1].Value;
            if (address.StartsWith("+86")) {
                address = address.Substring(3);
            }
            string content1 = content[1].TrimEnd('\r');
            if (content1.StartsWith("050003")) {
                content1 = content1.Substring(12);
            }

            SMS sms = new SMS(address, SMSHelper.SMSDecode(content1));
            sms.Raw = content[1].TrimEnd('\r');
            sms.Flags = 0;
            sms.CreatedAt = DateTime.Now;

            deleteByIndex(index);
            Receive(sms);
        }

        private bool OnBeginRING(List<string> content) {
            return true;
        }

        private void OnRING(List<string> content) {

        }

        private void OnCMGSResponse(ModemResponse response) {
            SendResult(response);
        }

        private void deleteByIndex(int index) {
            port.Write(string.Format("AT+CMGD={0}\r", index));
        }

        private void AddRequestToQueue(ModemMessage arg) {
            if (arg is ModemRequest) {
                requestQueue.Enqueue(arg as ModemRequest);
            }
        }

        private List<string> receiveBuffer = new List<string>();
        private ATReceivedEventHandler interruptHandler;
        private ATBeginReceivedEventHandler beginInterruptHandler;
        private bool isInterrupt { get { return beginInterruptHandler != null; } }

        private Queue<ModemRequest> requestQueue = new Queue<ModemRequest>();
        private Dictionary<Type, ModemResponseHandler> responseMap = new Dictionary<Type, ModemResponseHandler>();
        private Dictionary<Regex, ATBeginReceivedEventHandler> ATBeginHandlerMap = new Dictionary<Regex, ATBeginReceivedEventHandler>();
        private Dictionary<Regex, ATReceivedEventHandler> ATHandlerMap = new Dictionary<Regex, ATReceivedEventHandler>();
        private string portName;
        private SerialPort port;
        private int index;
        private bool isOpen = false;

        public event SMSReceivedEventHandler Receive;
        public event SMSSendEventHandler SendResult;
    }

    public delegate bool ATBeginReceivedEventHandler(List<string> content);
    public delegate void ATReceivedEventHandler(List<string> content);
    public delegate void ModemResponseHandler(ModemResponse response);
    public delegate void SMSReceivedEventHandler(SMS arg);
    public delegate void SMSSendEventHandler(ModemResponse response);

}