短信服务器开发文档.docx
《短信服务器开发文档.docx》由会员分享,可在线阅读,更多相关《短信服务器开发文档.docx(13页珍藏版)》请在冰豆网上搜索。
短信服务器开发文档
{短信系统}
体系结构设计报告
文件状态:
[√]草稿
[]正式发布
[]正在修改
文件标识:
sms-1.0
当前版本:
1.0
作者:
完成日期:
济南博软
目录
0.文档介绍-2-
0.1文档目的-2-
0.2文档范围-2-
0.3读者对象-2-
0.4参考文献-2-
1.系统概述-3-
2.设计约束-3-
3.设计策略-3-
4.系统总体结构-4-
5.各业务模块的结构与功能-5-
6.开发环境的配置-12-
7.运行环境的配置-12-
8.测试-12-
0.文档介绍
0.1文档目的
对短信系统的体系架构和各个模块的结构进行描述,并给出本系统开发、测试和运行的配置。
0.2文档范围
c#webservice、winform、android、php开发相关
0.3读者对象
参与项目的研发人员及后续项目维护人员
0.4参考文献
无
1.系统概述
短信系统是一个利用android手机进行发短信的系统。
主要实现:
wenservice提供接口,android终端发送短信,winform守护程序,php的操作页面。
2.设计约束
✧需求约束。
参考需求文档《短信服务器部署文档》。
✧软件、硬件环境(包括运行环境和开发环境)的约束参考下文环境配置部分。
✧各个模块直接的接口定义要清晰、易用、通用。
✧用户界面要清晰、美观。
✧对各个功能模块进行严格的封装,并制定统一的接口规范,保证系统的正确性、健壮性、可靠性、效率(性能)、易用性、清晰性、安全性、可扩展性、兼容性、可移植性。
✧系统的总体架构要进行合理的分层、采用多线程技术提高系统可支持的并发量。
3.设计策略
根据产品的需求与发展战略,短信系统遵循如下的设计策略(DesignStrategy)。
✧扩展策略:
将各个模块进行严格的封装,并规范各个模块直接的接口,提高系统的可扩展性。
✧复用策略:
封装字符串、数据库访问、时间处理等常用的操作进行封装,并将系统的各个功能封装为函数。
✧折衷策略:
通过后期的测试调优,提供系统性能和耗费资源的最佳方案。
4.系统总体结构
短信系统是通过webservice接收短信内容,通过TCP发送给手机,手机利用android系统的短信接口发送短信。
系统包含四个模块,webservice提供接口几首提交的数据,android发送短信,winform程序守护系统,php的操作页面。
5.各业务模块的结构与功能
下面对短信系统的各模块进行具体说明.
前台:
这里的前台指php的操作页面。
后台:
主要是wenservice、android、winform。
5.1、webservice模块
Webservice为接口程序(后称接口),调用接口需提供商户的标识(短信验证时为AP的标识),手机号,短信内容。
查找AP标识对应的商户ID
publicstringSendSms(Stringuser,Stringmobiles,Stringcontents)
{
//if(user=="1000001")
if(user.Length==7)
{
returnsms(user,mobiles,contents);
}
else
{
StringsqlInsert="selectcompany_idfromapms_apwheredevice_code='"+user+"'";
DataSetds=read_jianquan(sqlInsert);
returnsms(ds.Tables[0].Rows[0]["company_id"].ToString(),mobiles,contents);
}
}
插入要发送的短信内容,把ip设置为空
Stringtime=tim();
StringsqlInsert="insertintosms_send_infovalues('','"+user+"','"+mobiles+"','"+contents+"','"+time+"',0,'');";
sms_mysql(sqlInsert);
查找用户,读取信息
sqlInsert="select*fromuser_info";
DataSetds_user=select_sms(sqlInsert);
判断用户的剩余短信数,查找设备发送短信
TcpClienttcp=newTcpClient(ds.Tables[0].Rows[i]["ip"].ToString(),50000);byte[]send=Encoding.GetEncoding("utf-8").GetBytes(mobiles+"-"+ds_user.Tables[0].Rows[u]["welcome"]+",您的验证码是:
"+contents+"-"+time);NetworkStreamns=tcp.GetStream();
ns.Write(send,0,send.Length);
tcp.Close();
读取mysql函数
publicstaticDataSetselect_sms(StringsqlInsert)
{
stringsource="database=sms_sudod_com;server=;userid=sms_sudod_com;pwd=anxun123";
MySqlConnectionconn=newMySqlConnection(source);
MySqlCommandmySqlCommand=getSqlCommand(sqlInsert,conn);
MySqlDataAdapterda=newMySqlDataAdapter();
da.SelectCommand=mySqlCommand;
DataSetds=newDataSet();
da.Fill(ds);
conn.Close();
conn.Dispose();
returnds;
}
修改mysql函数
publicstaticstringsms_mysql(StringsqlInsert)
{
stringsource="database=sms_sudod_com;server=;userid=sms_sudod_com;pwd=anxun123";
MySqlConnectionconn=newMySqlConnection(source);
conn.Open();
MySqlCommandmySqlCommand=getSqlCommand(sqlInsert,conn);
mySqlCommand.CommandTimeout=1000;//超时
stringdata=mysql(mySqlCommand);
conn.Close();
returndata;
}
5.2、android模块
手机终端开机自起:
先在配置文件里面注册一个广播,监听开机事件,然后在result.java里面设置开机启动
publicclassresultextendsBroadcastReceiver{
@Override
publicvoidonReceive(Contextarg0,Intentarg1){
//TODOAuto-generatedmethodstub
Intenti=newIntent(arg0,Sendsms.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
arg0.startActivity(i);
}
}
TCP的建立和读取
classSocketServerThreadimplementsRunnable{
publicvoidrun(){
//TODOAuto-generatedmethodstub
try{
while(thread_flag){
try{
client_index=client_index%MAXSIZE;
client[client_index]=serverSocket.accept();
thread_read_flag=true;
newThread(newReadThread(client_index)).start();
client_index++;
Thread.sleep(1000);
}catch(Exceptione){
//TODO:
handleexception
Toast.makeText(Sendsms.this,"tcp",Toast.LENGTH_SHORT).show();
}
}
}catch(Exceptione){
thread_flag=false;
thread_read_flag=false;
}
}
}
classReadThreadimplementsRunnable{
intindex;
publicReadThread(intindex){
this.index=index;
}
publicvoidrun(){
byte[]data=newbyte[1024];
//TODOAuto-generatedmethodstub
try{
while(true){
inputStream=client[index].getInputStream();
intreadBytes=inputStream.read(data);
if(readBytes==0)
continue;
rec_str.append(newString(data,0,readBytes));
runOnUiThread(newRunnable(){
publicvoidrun(){
//TODOAuto-generatedmethodstub
add_rec=add_rec+rec_str.toString()+"\n";
edit_receive.setText(add_rec);
send_data=rec_str.toString().split("-");
newThread(newsms_Send()).start();
rec_str.delete(0,rec_str.length());
}
});
}
}catch(Exceptione){
//TODOAuto-generatedcatchblock
thread_read_flag=false;
}finally{
try{
inputStream.close();
}catch(IOExceptione){
//TODOAuto-generatedcatchblock
}
}
}
}
发送短信
privatevoidsend(finalStringphoneNumber,finalStringmessage){
if(phoneNumber.equals("")){
}else{
ok_num=0;
error_num=0;
//---sendsanSMSmessagetoanotherdevice---
finalSmsManagersms=SmsManager.getDefault();
StringSENT_SMS_ACTION="SENT_SMS_ACTION";
//createthesentIntentparameter
IntentsentIntent=newIntent(SENT_SMS_ACTION);
finalPendingIntentsentPI=PendingIntent.getBroadcast(this,0,sentIntent,0);
if(message.length()>70){
ArrayListmsgs=sms.divideMessage(message);
for(Stringmsg:
msgs){
sms.sendTextMessage(phoneNumber,null,msg,sentPI,null);
}
}else{
sms.sendTextMessage(phoneNumber,null,message,sentPI,null);
}
//registertheBroadcastReceivers
registerReceiver(newBroadcastReceiver(){
@Override
publicvoidonReceive(Context_context,Intent_intent){
switch(getResultCode()){
caseActivity.RESULT_OK:
//成功
if(ok_num<1){
ok_num++;
Toast.makeText(getBaseContext(),
phoneNumber+":
"+message+"->"+ok(time)+"->"+time,Toast.LENGTH_SHORT)
.show();
}
break;
default:
if(error_num<1){
error_num=error_num+1;
error=error+1;
t_error.setText(String.valueOf(error));
//重发
/*if(message.length()>70){
ArrayListmsgs=sms.divideMessage(message);
for(Stringmsg:
msgs){
sms.sendTextMessage(phoneNumber,null,msg,sentPI,null);
}
}else{
sms.sendTextMessage(phoneNumber,null,message,sentPI,null);
}*/
}
break;
}
}
},newIntentFilter(SENT_SMS_ACTION));
}
}
5.3、winform模块
开机自起
privatevoidSetAutoStart()
{
stringKJLJ=Application.ExecutablePath;
if(!
System.IO.File.Exists(KJLJ))//判断指定文件是否存在
return;
stringnewKJLJ=KJLJ.Substring(KJLJ.LastIndexOf("\\")+1);
RegistryKeyRkey=
Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",true);
if(Rkey==null)
Rkey=Registry.LocalMachine.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
Rkey.SetValue(newKJLJ,KJLJ);
MessageBox.Show("程序设置完毕,请重新启动计算机后即可生效!
","重新启动!
",MessageBoxButtons.OK,MessageBoxIcon.Information);
}
每日0时清空日发送短信数,每月1日清空月发送短信数,判断当天的短信发送数,每个手机平均发送130以上后会短信提醒,判断每月的短信发送数,每月短信总数剩余不足100条时短信提醒,判断用户的短信剩余数,如果不足十条提醒,判断手机是否在线,如果掉线提醒。
publicboolPing(stringip)
{
System.Net.NetworkInformation.Pingp=newSystem.Net.NetworkInformation.Ping();
System.Net.NetworkInformation.PingOptionsoptions=newSystem.Net.NetworkInformation.PingOptions();
options.DontFragment=true;
stringdata="1";
byte[]buffer=Encoding.ASCII.GetBytes(data);
inttimeout=100;//Timeout时间,单位:
毫秒
try
{
System.Net.NetworkInformation.PingReplyreply=p.Send(ip,timeout,buffer,options);
if(reply.Status==System.Net.NetworkInformation.IPStatus.Success)
returntrue;
else
returnfalse;
}
catch
{
}
returnfalse;
}
6.开发环境的配置
类别
标准配置
最低配置
软件
IIS
Eclipse
Androidsdk
Jdk
Vs2013
Zend
Mysql
IIS
Eclipse
Androidsdk
Jdk
Vs2013
Zend
Mysql
网络通信
TCP/IP
TCP/IP
其它
无
无
7.运行环境的配置
类别
标准配置
最低配置
手机
Android2.3.3
Android2.3.3
软件
IIS
Mysql
Apache
Mysql.data
IIS
Mysql
Apache
Mysql.data
网络通信
TCP/IP
TCP/IP
其它
无
无
8.测试
1、在短信认证页面发送短信:
可正常发送,时间在16s左右
2、同时发送多天短信:
经测试,一个手机1s可接受发送短信为为1条,服务器1s会分配2条短信给同一手机,可正常发送
3、手机和服务器每天0时重启,程序自动运行