文章来自:https://blog.csdn.net/IT_xiao_guang_guang/article/details/104299983


前言

  1.发送手机验证码用的是网建的SMS接口(http://sms.webchinese.cn/

  2.手机验证码简单的做了以下限制:

    ①发送验证码1分钟只能点击发送1次

    ②相同IP手机号码1天最多提交20次(这里我用的是本地局域网IP)

    ③加入图形验证码

  注:SMS官网上的建议还有要对手机号码次数进行限制:单个手机号码30分钟最多提交10次。(这个和IP限制次数方法是一样的,我这里没加)


功能实现

一、功能界面

二、创建图形验证码类

关于图形验证码,也可以参照我的这篇文章:C# WinForm 登录界面的图片验证码


创建产生图形验证码的类:

  ①生成随机验证码字符串,用的是Random随机函数,用GUID生成6位随机数

  ②创建验证码图片,将该字符串画在PictureBox控件中


ImageVeriCodeClass:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;//绘图
using System.Windows.Forms; namespace SMSVeriCode
{
public class ImageVeriCodeClass
{
#region 图片验证码功能
/// <summary>
/// 生成随机验证码字符串
/// </summary>
public static string CreateRandomImageCode(int CodeLength)
{
int randNum;
char code;
string randomCode = String.Empty;//随机验证码 //生成一定长度的随机验证码
//Random random = new Random();//生成随机数对象
for (int i = 0; i < CodeLength; i++)
{
//利用GUID生成6位随机数
byte[] buffer = Guid.NewGuid().ToByteArray();//生成字节数组
int seed = BitConverter.ToInt32(buffer, 0);//利用BitConvert方法把字节数组转换为整数
Random random = new Random(seed);//以生成的整数作为随机种子
randNum = random.Next(); //randNum = random.Next();
if (randNum % 3 == 1)
{
code = (char)('A' + (char)(randNum % 26));//随机大写字母
}
else if (randNum % 3 == 2)
{
code = (char)('a' + (char)(randNum % 26));//随机小写字母
}
else
{
code = (char)('0' + (char)(randNum % 10));//随机数字
}
randomCode += code.ToString();
}
return randomCode;
} /// <summary>
/// 创建验证码图片
/// </summary>
public static void CreateImage(string strValidCode, PictureBox pbox)
{
try
{
int RandAngle = 45;//随机转动角度
int MapWidth = (int)(strValidCode.Length * 21);
Bitmap image = new Bitmap(MapWidth, 28);//验证码图片大小-宽和高 //创建绘图对象Graphics
Graphics graph = Graphics.FromImage(image);
graph.Clear(Color.AliceBlue);//清除绘画面,填充背景色
graph.DrawRectangle(new Pen(Color.Black, 0), 0, 0, image.Width - 1, image.Height - 1);//画一个边框
graph.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;//模式
Random rand = new Random();
//背景噪点生成
Pen blackPen = new Pen(Color.LightGray, 0);
for (int i = 0; i < 50; i++)
{
int x = rand.Next(0, image.Width);
int y = rand.Next(0, image.Height);
graph.DrawRectangle(blackPen, x, y, 1, 1);
}
//验证码旋转,防止机器识别
char[] chars = strValidCode.ToCharArray();//拆散字符串成单字符数组
//文字居中
StringFormat format = new StringFormat(StringFormatFlags.NoClip);
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center;
//定义颜色
Color[] c = { Color.Black, Color.Red, Color.DarkBlue, Color.Green, Color.Orange, Color.Brown, Color.DarkCyan, Color.Purple };
//定义字体
string[] font = { "Verdana", "Microsoft Sans Serif", "Comic Sans MS", "Arial", "宋体" };
for (int i = 0; i < chars.Length; i++)
{
int cindex = rand.Next(7);
int findex = rand.Next(5);
Font f = new System.Drawing.Font(font[findex], 13, System.Drawing.FontStyle.Bold);//字体样式(参数2为字体大小)
Brush b = new System.Drawing.SolidBrush(c[cindex]);
Point dot = new Point(16, 16); float angle = rand.Next(-RandAngle, RandAngle);//转动的度数
graph.TranslateTransform(dot.X, dot.Y);//移动光标到指定位置
graph.RotateTransform(angle);
graph.DrawString(chars[i].ToString(), f, b, 1, 1, format); graph.RotateTransform(-angle);//转回去
graph.TranslateTransform(2, -dot.Y);//移动光标到指定位置
}
pbox.Image = image;
}
catch (ArgumentException)
{
MessageBox.Show("验证码图片创建错误");
}
}
#endregion
}
}

三、创建存储IP地址的数据库表

对于IP次数的限制,我是把IP地址存在了数据库的表里。


①先创建一个数据库SMSVeriCode

②创建tIP表的sql语句:

create table tIP
(
IP nvarchar(32), --IP地址
SendTimes int, --发送次数
SMSVeriCodeTime datetime2 --手机验证码发送时间
)

---

四、创建手机验证码类

创建发送手机验证码的类:

  ①发送手机验证码功能

  ②验证国内手机号

  ③根据IP地址限制手机号码1天最多提交20次

  ④获取本地IP地址信息(局域网IP)


SMSVeriCodeClass:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
//需要用到的命名空间
using System.IO;
using System.Net;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Data.SqlClient;
using System.Net.Sockets; namespace SMSVeriCode
{
public class SMSVeriCodeClass
{
#region 手机验证码功能
/// <summary>
/// 获取随机验证码
/// 利用GUID获取随机数
/// </summary>
/// <param name="Phone">手机号</param>
/// <param name="MinSeed">随机数最小值</param>
/// <param name="MaxSeed">随机数最大值</param>
/// <returns>随机验证码</returns>
public static string GetSMSValidCode(int MinSeed, int MaxSeed)
{
byte[] pbyte = Guid.NewGuid().ToByteArray();//生成字节数组
int seed = BitConverter.ToInt32(pbyte, 0);//利用BitConvert方法把字节数组转换为整数
Random random = new Random(seed);//以生成的整数作为随机种子
string smsVeriCode = random.Next(MinSeed, MaxSeed).ToString(); return smsVeriCode;
} /// <summary>
/// 发送验证码的函数
/// </summary>
/// <param name="Phone"></param>
/// <param name="textContent"></param>
/// <returns>返回发送的结果:数字</returns>
public static string SendSMSVeriCode(string UidName, string KeyMD5, string Phone, string TextContent)
{
string strUrl = "http://utf8.sms.webchinese.cn/?";//UTF-8编码Url
string strUidName = "Uid=";//SMS平台的用户名
string strKeyMD5 = "&key=";//SMS平台的接口密匙;strKeyMD5=接口密钥32位MD5加密(大写)
string strPhone = "&smsMob=";//目的手机号码
string strTextContent = "&smsText="; //短信内容;普通短信70个字/条 strUrl = strUrl + strUidName + UidName + strKeyMD5 + KeyMD5 + strPhone + Phone + strTextContent + TextContent; string SMSResult = GetFromUrl(strUrl);//发送短信,得到返回值
//MessageBox.Show(Result); //string JudgeResult = GetResult(SMSResult);//判断返回值
//return JudgeResult; return SMSResult;
} /// <summary>
/// 发送短信,得到返回值
/// </summary>
public static string GetFromUrl(string url)
{
string strReturn = null; if (url == null || url.Trim().ToString() == "")
{
return strReturn;
}
else//手机号正确
{
string targeturl = url.ToString();
try
{
HttpWebRequest hr = (HttpWebRequest)WebRequest.Create(targeturl);
hr.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)";
hr.Method = "GET";
hr.Timeout = 30 * 60 * 1000; //30分钟超时
WebResponse hs = hr.GetResponse();
Stream sr = hs.GetResponseStream();
StreamReader ser = new StreamReader(sr, Encoding.Default);
strReturn = ser.ReadToEnd();
}
catch (Exception ex)
{
strReturn = null;
MessageBox.Show(ex.Message);
}
}
return strReturn;
} /// <summary>
/// 判断返回值
/// </summary>
public static string GetResult(string strReturn)
{
int result = 0;
try
{
result = int.Parse(strReturn);
switch (result)
{
case -1:
strReturn = "没有该用户账户";
break;
case -2:
strReturn = "接口密钥不正确,不是账户登陆密码";
break;
case -21:
strReturn = "MD5接口密钥加密不正确";
break;
case -3:
strReturn = "短信数量不足";
break;
case -11:
strReturn = "该用户被禁用";
break;
case -14:
strReturn = "短信内容出现非法字符";
break;
case -4:
strReturn = "手机号格式不正确";
break;
case -41:
strReturn = "手机号码为空";
break;
case -42:
strReturn = "短信内容为空";
break;
case -51:
strReturn = "短信签名格式不正确,接口签名格式为:【签名内容】";
break;
case -52:
strReturn = "短信签名太长";
break;
case -6:
strReturn = "IP限制";
break;
default:
strReturn = "成功发送" + result + "条短信!";
break;
}
}
catch (Exception ex)
{
strReturn = ex.Message;
}
return strReturn;
}
#endregion /// <summary>
/// 验证国内手机号
/// </summary>
/// <param name="phone">手机号</param>
/// <returns></returns>
public static bool CheckMobilePhone(string phone)
{
//电信手机号码正则
string dianxin = @"^1[3578][01379]\d{8}$";
Regex dReg = new Regex(dianxin);
//联通手机号正则
string liantong = @"^1[34578][01256]\d{8}$";
Regex tReg = new Regex(liantong);
//移动手机号正则
string yidong = @"^(134[012345678]\d{7}|1[34578][012356789]\d{8})$";
Regex yReg = new Regex(yidong); if (dReg.IsMatch(phone) || tReg.IsMatch(phone) || yReg.IsMatch(phone))
{
return true;
}
return false;
} #region 根据IP限制手机号码1天最多提交20次
/// <summary>
/// 发送次数清零
/// </summary>
public static int ResetSendTimes(string IP)
{
string connString = "server=.;database=SMSVeriCode;uid=test;pwd=test";
SqlConnection pSqlConnection = new SqlConnection(connString);
pSqlConnection.Open(); string sqlReset = "update tIP set SendSMSTimes=0 where IP='" + IP + "'"; SqlCommand sqlcmdReset = new SqlCommand(sqlReset, pSqlConnection); return sqlcmdReset.ExecuteNonQuery();
} /// <summary>
/// 更新已发送的次数
/// </summary>
public static int UpdateSendTimes(string IP)
{
string connString = "server=.;database=SMSVeriCode;uid=test;pwd=test";
SqlConnection pSqlConnection = new SqlConnection(connString);
pSqlConnection.Open(); string sqlUdpate = "update tIP set SendSMSTimes = SendSMSTimes + 1 where IP='" + IP + "'"; SqlCommand sqlcmdUpdate = new SqlCommand(sqlUdpate, pSqlConnection); return sqlcmdUpdate.ExecuteNonQuery();
} /// <summary>
/// 更新手机验证码发送时间
/// </summary>
public static int UpdateSMSCodeTime(string IP)
{
string connString = "server=.;database=SMSVeriCode;uid=test;pwd=test";
SqlConnection pSqlConnection = new SqlConnection(connString);
pSqlConnection.Open(); string sqlUpdateTime = "update tIP set SMSVeriCodeTime=getdate() where IP='" + IP + "'"; SqlCommand sqlcmdUpdateTime = new SqlCommand(sqlUpdateTime, pSqlConnection); return sqlcmdUpdateTime.ExecuteNonQuery();
}
#endregion /// <summary>
/// 获取本地IP地址信息
/// </summary>
public static string GetLocalIP()
{
try
{
string HostName = Dns.GetHostName();//主机名
IPHostEntry ip = Dns.GetHostEntry(HostName); for (int i = 0; i < ip.AddressList.Length; i++)
{
//AddressFamily.InterNetwork表示IPV4
//AddressFamily.InterNetworkV6表示IPV6
if (ip.AddressList[i].AddressFamily == AddressFamily.InterNetwork)
{
return ip.AddressList[i].ToString();
}
}
return "";
}
catch (Exception ex)
{
MessageBox.Show("GetLocalIP Error!" + ex.Message);
return "";
}
}
}
}

五、在Form1中调用以上两个类中的函数,实现功能

注:

  以下代码中的"用户名"和"密钥",要去SMS网站中查看。

string UidName = "XXXXXXX";//SMS平台的用户名
string KeyMD5 = "XXXXXXXX";//SMS平台的接口密匙;

IP次数限制的大致思路——相同IP手机号码1天最多提交20次:

  ①用户发送验证码,获取其IP地址,判断数据表中是否已经有了这个IP;

  如果没有就向数据表中插入这个新的IP地址,接着发送验证码,在表中更新发送次数+1;

  ②如果查询到表中已经有了这个IP地址,就判断其是否满足条件(发送次数<=20,时间<24小时);

  ③如果不满足条件,直接返回,不往下继续执行程序;

  ④如果满足条件,往下执行程序,发送验证码。(同时要注意查询表中的发送次数是否为0,要更新发送时间)

Form1.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms; namespace SMSVeriCode
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
} #region 图片验证码
private const int ImageVeriCodeLength = 4;//验证码长度
private String strImageVeriCode = "";//验证码 //更新图片验证码
private void UpdateImageVeriCode()
{
strImageVeriCode = ImageVeriCodeClass.CreateRandomImageCode(ImageVeriCodeLength);//生成随机验证码
if (strImageVeriCode == "") return;
ImageVeriCodeClass.CreateImage(strImageVeriCode, pbox1);//创建验证码图片
}
#endregion //窗体加载时更新图片验证码
private void Form1_Load(object sender, EventArgs e)
{
UpdateImageVeriCode();
} //点击PictureBox更新图片验证码
private void pbox1_Click(object sender, EventArgs e)
{
UpdateImageVeriCode();
} /// <summary>
/// 获取手机验证码
/// </summary>
int seconds1 = 60;//倒计时60s
int seconds2 = 60 * 5;//验证码有效时间5分钟
string strSMSVeriCode;
private void btnSendVeriCode_Click(object sender, EventArgs e)
{
//获取文本框中的数据
string phone = txtPhone.Text.Trim();//手机号
string imagevericode = txtImageVeriCode.Text.Trim();//图片验证码 strSMSVeriCode = SMSVeriCodeClass.GetSMSValidCode(100000, 999999);//随机6位SMS验证码
int totalTime = 5;//SMS验证码有效时长
string smsTextContent = "验证码:" + strSMSVeriCode + "," + totalTime + "分钟内有效,请勿泄漏于他人。如非本人操作,请忽略。";//SMS短信文本内容
string UidName = "XXXXXXX";//SMS平台的用户名
string KeyMD5 = "XXXXXXXX";//SMS平台的接口密匙; if (String.IsNullOrEmpty(phone))//判断是否输入了手机号
{
MessageBox.Show("请输入手机号!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
txtPhone.Focus();
}
else if (SMSVeriCodeClass.CheckMobilePhone(phone) == false)//判断手机号格式是否正确
{
MessageBox.Show("请输入有效的11位手机号码", "警告", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
txtPhone.Focus();
}
else if (String.IsNullOrEmpty(imagevericode))//判断是否输入了图片验证码
{
MessageBox.Show("请输入图片验证码!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
txtImageVeriCode.Focus();
}
else if (imagevericode.ToLower() != strImageVeriCode.ToLower())//判断图片验证码输入是否正确;不区分大小写
{
MessageBox.Show("您输入的验证码有误!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
UpdateImageVeriCode();
txtImageVeriCode.Text = "";
txtImageVeriCode.Focus();
}
else//发送SMS验证码
{
string ip = SMSVeriCodeClass.GetLocalIP(); string connString = "server=.;database=SMSVeriCode;uid=test;pwd=test";
SqlConnection pSqlConnection = new SqlConnection(connString);
pSqlConnection.Open(); string sqlIP = "select *,datediff(hour,SMSVeriCodeTime,getdate()) as TimeIntervel from tIP where IP='" + ip + "'";
SqlCommand sqlcmdIP = new SqlCommand(sqlIP, pSqlConnection);
SqlDataReader sdr = sqlcmdIP.ExecuteReader();
sdr.Read();
if (sdr.HasRows == true)//表中已有此IP地址
{
if (sdr.GetInt32(1) == 20 && sdr.GetInt32(3) <= 24)//20次,24小时
{
MessageBox.Show("相同IP手机号码1天最多提交20次!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
UpdateImageVeriCode();
txtImageVeriCode.Text = "";
return;
}
else if (sdr.GetInt32(1) == 20 && sdr.GetInt32(3) > 24)
{
SMSVeriCodeClass.ResetSendTimes(ip);//发送次数置零
} if (sdr.GetInt32(1) == 0)//次数为0时
{
string SMSResult = SMSVeriCodeClass.SendSMSVeriCode(UidName, KeyMD5, phone, smsTextContent);//发送
if (Convert.ToInt32(SMSResult) > 0)//成功发送SMS验证码
{
//倒计时开始
timer1.Interval = 1000;
timer1.Start();
timer2.Interval = 1000;
timer2.Start(); btnSendVeriCode.Enabled = false;
UpdateImageVeriCode();
txtImageVeriCode.Text = ""; SMSVeriCodeClass.UpdateSendTimes(ip);//更新发送次数+1
SMSVeriCodeClass.UpdateSMSCodeTime(ip);//更新发送时间
}
else//发送SMS验证码失败
{
string JudetResult = SMSVeriCodeClass.GetResult(SMSResult);
MessageBox.Show(JudetResult, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
else
{
string SMSResult = SMSVeriCodeClass.SendSMSVeriCode(UidName, KeyMD5, phone, smsTextContent);//发送
if (Convert.ToInt32(SMSResult) > 0)//成功发送SMS验证码
{
//倒计时开始
timer1.Interval = 1000;
timer1.Start();
timer2.Interval = 1000;
timer2.Start(); btnSendVeriCode.Enabled = false;
UpdateImageVeriCode();
txtImageVeriCode.Text = ""; SMSVeriCodeClass.UpdateSendTimes(ip);//更新发送次数+1
}
else//发送SMS验证码失败
{
string JudetResult = SMSVeriCodeClass.GetResult(SMSResult);
MessageBox.Show(JudetResult, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
else//表中没有此IP地址—第一次发送验证码
{
string smsSendTime = DateTime.Now.ToString();//SMS验证码发送时间 //--------向数据表tIP中添加信息------//
pSqlConnection.Close();
pSqlConnection.Open(); string sqlInsert = "insert into tIP(IP,SendSMSTimes,SMSVeriCodeTime)";
sqlInsert += "values('{0}','{1}','{2}')";
sqlInsert = string.Format(sqlInsert, ip,"0",smsSendTime); SqlCommand sqlcmdInsert = new SqlCommand(sqlInsert, pSqlConnection);
sqlcmdInsert.ExecuteNonQuery(); //--------------发送验证码----------------//
string SMSResult = SMSVeriCodeClass.SendSMSVeriCode(UidName, KeyMD5, phone, smsTextContent);//发送
if (Convert.ToInt32(SMSResult) > 0)//成功发送SMS验证码
{
//倒计时开始
timer1.Interval = 1000;
timer1.Start();
timer2.Interval = 1000;
timer2.Start(); btnSendVeriCode.Enabled = false;
UpdateImageVeriCode();
txtImageVeriCode.Text = ""; SMSVeriCodeClass.UpdateSendTimes(ip);//更新发送次数+1
}
else//发送SMS验证码失败
{
string JudetResult = SMSVeriCodeClass.GetResult(SMSResult);
MessageBox.Show(JudetResult, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
} /// <summary>
/// 倒计时—SMS验证码1分钟只能点击发送1次
/// </summary>
private void timer1_Tick(object sender, EventArgs e)
{
if (seconds1 > 0)
{
seconds1--;
btnSendVeriCode.Text = "剩余" + seconds1.ToString() + "秒";
}
else
{
timer1.Stop(); btnSendVeriCode.Text = "获取验证码";
btnSendVeriCode.Enabled = true;
}
} /// <summary>
/// 手机SMS验证码5分钟内有效;但是如果有新的验证码出现,旧验证码就会失效
/// </summary>
private void timer2_Tick(object sender, EventArgs e)
{
if (seconds2 == 0)
{
timer2.Stop(); //旧的验证码过期,生成一个新的验证码
strSMSVeriCode = SMSVeriCodeClass.GetSMSValidCode(100000, 999999);
}
} /// <summary>
/// 确认按钮
/// </summary>
private void btnConfirm_Click(object sender, EventArgs e)
{
//获取文本数据
string smsvericode = txtSMSVeriCode.Text.Trim();//手机SMS验证码 if (String.IsNullOrEmpty(smsvericode))
{
MessageBox.Show("请输入手机验证码!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
txtSMSVeriCode.Focus();
}
else if (smsvericode != strSMSVeriCode)//判断手机SMS验证码是否输入正确
{
MessageBox.Show("您输入的验证码有误!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
txtSMSVeriCode.Focus();
}
else
{
MessageBox.Show("验证成功!");
}
}
}
}

C# WinForm 使用SMS接口发送手机验证码+图形验证码+IP限制的更多相关文章

  1. SNF开发平台WinForm之十二-发送手机短信功能调用-金笛-SNF快速开发平台3.3-Spring.Net.Framework

    1.调用前组装参数 2.调用发送信息服务脚本   .调用前组装参数: BaseSendTaskEntity entity = new BaseSendTaskEntity(); entity.Mess ...

  2. 四:java调接口实现发送手机短信验证码功能

    1.点击获取验证码之前的样式: 2.输入正确的手机号后点击获取验证码之后的样式: 3.如果手机号已经被注册的样式: 4.如果一个手机号一天发送超过3次就提示不能发送: 二:前台的注册页面的代码:reg ...

  3. Java调用WebService接口实现发送手机短信验证码功能,java 手机验证码,WebService接口调用

    近来由于项目需要,需要用到手机短信验证码的功能,其中最主要的是用到了第三方提供的短信平台接口WebService客户端接口,下面我把我在项目中用到的记录一下,以便给大家提供个思路,由于本人的文采有限, ...

  4. Java调用阿里云短信接口发送手机验证码

    前五步可参考阿里云服务文档:https://help.aliyun.com/document_detail/59210.html?spm=a2c4g.11174283.4.1.2b152c42DoJ7 ...

  5. java后台通过Servlet给用户发送手机短信验证码,第一次写勿喷,欢迎转载

    短信验证码跟自己在Servlet画的验证码不一样,我们不用管短信验证码是怎么产生的,我们只需要关注如何调用短信验证码,在短信验证码里面添加 自己需要的随机数或者其他的内容. 现在直接上流程 第一步找一 ...

  6. django之集成阿里云通信(发送手机短信验证码)

    python3 + django2.0 集成 "阿里云通信" 服务: (SDK文档地址:https://help.aliyun.com/document_detail/55491. ...

  7. C# WinForm 使用SMTP协议发送QQ邮箱验证码

    文章来自:https://blog.csdn.net/IT_xiao_guang_guang/article/details/104336604 前言   在程序设计中,发送验证码是常见的一个功能,用 ...

  8. Java实现发送手机验证码功能(短信+语音)

    利用第三方平台可以实现发送手机短信验证码和语音验证码的功能,本文使用框架是struts2+spring+hibernate,现就action层给出核心代码功能. public class Verify ...

  9. 利用java实现的一个发送手机短信的小例子

    今天闲来无事,在微博上看到一个关于用java实现的一个发送手机短信的程序,看了看,写的不太相信,闲的没事,把他整理下来,以后可能用得着 JAVA发送手机短信,流传有几种方法:(1)使用webservi ...

随机推荐

  1. Python for Data Analysis 学习心得(一) - numpy介绍

    一.简介 Python for Data Analysis这本书的特点是将numpy和pandas这两个工具介绍的很详细,这两个工具是使用Python做数据分析非常重要的一环,numpy主要是做矩阵的 ...

  2. MySQL 持久化保障机制-redo 日志

    我们在 聊一聊 MySQL 中的事务及其实现原理 中提到了 redo 日志,redo 日志是用来保证 MySQL 持久化功能的,需要注意的是 redo 日志是 InnoDB 引擎特有的功能. 为什么 ...

  3. ArcGIS for JavaScript 开发智能提示

    开发如果没有智能提示,可想而知是一件多举痛苦的事情,好在Esri为Visual Studio 2010.Aptana3提供了一个插件,这样就使我们在使用ArcGIS API for Javascrip ...

  4. springboot +fastdfs 上传文件到到云服务器

    fastdfs在云服务器的搭建和配置:https://blog.csdn.net/qq_41592652/article/details/104006289 springboot结构如下: appli ...

  5. 最大流入门题目 - poj 1273

    Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clover patch. This ...

  6. Maven 基础环境搭建 项目依赖jar包导入

    一.创建一个Maven工程 不清楚的话请查阅其它文档. 二.引入项目依赖的jar包 1.Spring 2.SpringMvc 3.Mybatis 4. 数据库连接池,驱动 5.其它(jstl.serv ...

  7. Python的re模块,正则表达式用法详解,正则表达式中括号的用法

    Python的re模块,正则表达式 #导入re模块 import  re 1.match方法的使用: result = re.match(正则表达式,待匹配的字符串) 正则表达式写法: 第一部分: 字 ...

  8. Docker + node(koa) + nginx + mysql 线上环境部署

    在上一篇 Docker + node(koa) + nginx + mysql 开发环境搭建,我们进行了本地开发环境搭建 现在我们就来开始线上环境部署 如果本地环境搭建没有什么问题,那么线上部署的配置 ...

  9. DataFrame数据合并

    一.join 作用:默认情况下,他是把行索引相同的数据合并到一起注意:以左为准,没有的部分用NaN补全 例子 import pandas as pd import numpy as np df1 = ...

  10. redis 数据类型之字典

    1.hset hset(name, key, value) # 参数:     # name,redis的name     # key,name对应的hash中的key     # value,nam ...