如何实现移动端和服务器端的通信
‘壹’ android、ios客户端和服务器通信一般使用什么方式,各有什么优缺点
1、从网络协议上来看,就http方式和socket方式。
2、http方式开发起来效率想对要高一点,但是对于推送这种来说,想对要难做点,因为http是短连接。socket这种方式开发要长,调试略微麻烦,但是做推送想对简单,可以建立一个长连接。
3、Web Service服务其实也是基于HTTP协议(它基于SOAP协议,而SOAP又是基于HTTP协议)。
最大缺点我觉得是Web Service实在是太厚重了,特别对于移动端来说,WSDL是基于XML,XML已经够厚重了,WSDL还有一些头信息,更加厚重。
而且JSON + HTTP的方式,相对来说就非常轻量级了,JSON格式数据本生就是javascript中的数据或者对象,所以在网络传输中具有非常明显优势,可以说本来就是网络传输用的,毫无违和感嘛:)
还有一个不能算缺点的缺点:目前移动端HTTP网络库多的要死,Web Service我所知道就是ksoap2,而且非常的难用。。。
‘贰’ 设备级、应用级和微应用级的双向认证安全隧道是如何区分和实施的
通过切面方式零改造嵌入,提供设备级、应用级和微应用级的双向认证安全隧道,实现移动端到服务端的动态访问控制和数据加密保护,保障移动业务的通信安全。
在技术实现中,设备级认证安全隧道主要关注设备本身的身份验证,通过硬件密钥或生物识别技术,确保设备的真实性。设备级安全隧道在用户设备和服务器之间建立加密通道,仅允许已认证的设备访问特定服务,有效防止非授权设备的接入。
应用级认证安全隧道则侧重于应用层面的身份验证,通过用户账号、密码或第三方身份验证服务,确认访问应用的合法用户。应用级安全隧道在用户和应用之间建立安全连接,确保数据传输的安全性,同时防止恶意软件或钓鱼攻击。
微应用级认证安全隧道更加细致,针对具体功能或服务模块进行认证保护。通过API密钥、OAuth等机制,实现对微应用的访问控制和数据加密。这种方式不仅提升了系统的安全性,还能灵活地管理不同服务的访问权限。
这三个层次的认证安全隧道相互配合,形成一个多层次的安全防护体系。设备级保障设备身份,应用级确保用户身份,微应用级细化功能访问控制,共同构建起移动端到服务端的安全通道。通过动态访问控制和数据加密,实现移动业务的全方位安全保护,有效抵御各种安全威胁。
总结来说,设备级、应用级和微应用级认证安全隧道通过不同层次的身份验证和数据保护机制,确保移动端到服务端的通信安全。它们共同构建了一个立体化的安全防护网络,为移动业务提供了坚实的保护,有效防止了未经授权的访问和数据泄露,保障了移动应用的稳定运行和用户数据的安全。
‘叁’ 如何实现android和服务器的长连接
转载 这种功能实际上就是数据同步,同时要考虑手机本身、电量、网络流量等等限制因素,所以通常在移动端上有一下两个解决方案:
1.一种是定时去server查询数据,通常是使用HTTP协议来访问web服务器,称Polling(轮询);
2.还有一种是移动端和服务器建立长连接,使用XMPP长连接,称Push(推送)。
从耗费的电量、流量和数据延迟性各方面来说,Push有明显的优势。但是使用Push的缺点是:
对于客户端:实现和维护相对成本高,在移动无线网络下维护长连接,相对有一些技术上的开发难度。
对于服务器:如何实现多核并发,cpu作业调度,数量庞大的长连接并发维护等技术,仍存在开发难点。
在讲述Push方案的原理前,我们先了解一下移动无线网络的特点。
移动无线网络的特点:
因为 IP v4 的 IP 量有限,运营商分配给手机凳裤终端的 IP 是运营商内网的 IP,手机要连接 Internet,就需要通过运营商的网关做一个网络地址转换(Network Address Translation,NAT)。简单的说运营商的网关需要维护一个外网 IP、端口到内网 IP、端口的对应关系,以确保内网的手机可以跟 Internet 的服务器通讯
GGSN(Gateway GPRS
Support Node 网关GPRS支持结点)模块就实现了NAT功能。
因为大部分移动无线网络运营商都是为了减少网关的NAT映射表的负荷,所以如果发现链路中有一段时间没有数据通讯时,会删除其对应表,造成链路中断。(关于NAT的作用及其原理可以查看我的另一篇博文:关于使用UDP(TCP)跨局域网,NAT穿透的心得)
Push在Android平台上长连接的实现:
既然我们知道我们移动端要和Internet进行通信,必须通过运营商的网关,所以,为了不让NAT映射表失效,我们需要定时向Internet发送数据,因为只是为了不然NAT映射表失效,所以只需发送长度为0的数据即可。
这时候就要用到定时器,在android系统上,定时器通常有一下两种:
1.java.util.Timer
2.android.app.AlarmManager
分析:
Timer:可以按照计划或者时间周期来执行相关的任务。但是Timer需要用WakeLock来让CPU保持唤醒状态,才能保证任务的执行,这样子会消耗大量流量;当CPU处于休眠的时候,就不能唤醒执行任务,所以应用于移动端明显是不合适。
AlarmManager:AlarmManager类是属于android系统封装好来管理RTC模块的管理类。悔粗销这里就涉及到RTC模块,要更好地了解两者的区别,就要明白两者真正的区别。
RTC(Real- Time Clock)实时闹钟在一个嵌入式系统中,通常采用RTC
来提供可靠的系统时间,包括时分秒和年月日等;而且要求在系统处于关碧游机状态下它也能够正常工作(通常采用后备电池供电),它的外围也不需要太多的辅助电路,典型的就是只需要一个高精度的32.768KHz
晶体和电阻电容等。(如果对这方面感兴趣,可以自己查阅相关资料,这里就说个大概)
好了,回来正题。所以,AlarmManager又称全局定时闹钟。这意味着,当我用使用AlarmManager来定时执行任务,CPU可以正常地休眠,只有在执行任务是,才唤醒CPU,这个过程是很短时间的。
下面简单来说明其使用:
1.类似于Timer功能:
//获得闹钟管理器
AlarmManager
am = (AlarmManager)getSystemService(ALARM_SERVICE);
//设置任务执行计划
am.setRepeating(AlarmManager.ELAPSED_REALTIME, firstTime, 5*1000,
sender);//从firstTime才开始执行,每隔5秒再执行
2.实现全局定时功能:
//获得闹钟管理器
AlarmManager
am = (AlarmManager)getSystemService(ALARM_SERVICE);
//设置任务执行计划
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime,
5*1000, sender);//从firstTime才开始执行,每隔5秒再执行
总结:在android客户端使用Push推送时,应该使用AlarmManager来实现心跳功能,使其真正实现长连接。
‘肆’ JAVA服务端android客户端如何通信
一、HTTP请求(APACHE的HttpClient实现)
服务器端,就是普通的servlet、Strutus2就可以
移动端
protected static String get(String url, List<NameValuePair> params) {
String resultMsg;
// 设置http请求配置
HttpParams parms = new BasicHttpParams();
parms.setParameter("charset", HTTP.UTF_8);
// 配置连接超时
HttpConnectionParams.setConnectionTimeout(parms, 10 * 1000);
// 设置请求超时
HttpConnectionParams.setSoTimeout(parms, 15 * 1000);
// 实例化HttpClient
HttpClient httpclient = new DefaultHttpClient(parms);
// 实例化HttpGet
HttpGet httpget = new HttpGet(url);
// 设置请求头
httpget.addHeader("Content-Type", "application/json");
httpget.addHeader("charset", HTTP.UTF_8);
try {
if (params.size() > 0)
url = url + "?" + URLEncodedUtils.format(params, HTTP.UTF_8);
HttpResponse resp = httpclient.execute(httpget);
int statusCode = resp.getStatusLine().getStatusCode();
if (statusCode == HttpStatus.SC_OK) {
StringBuffer result = getResponse(resp);
resultMsg = result.toString();
} else {
resultMsg = "连接异常";
}
} catch (Exception e) {
resultMsg = "连接异常";
} finally {
// 关闭get
httpget.abort();
// 关闭连接 ,释放资源
httpclient.getConnectionManager().shutdown();
}
return resultMsg;
}
protected static String post(String uri, Object params) {
String resultMsg;
// 设置http请求配置
HttpParams hp = new BasicHttpParams();
hp.setParameter("charset", HTTP.UTF_8);
// 配置连接超时
HttpConnectionParams.setConnectionTimeout(hp, 10 * 1000);
HttpConnectionParams.setSoTimeout(hp, 15 * 1000);
// 实例化HttpClient
HttpClient httpclient = new DefaultHttpClient(hp);
// 实例化HttpPost请求
HttpPost httppost = new HttpPost(uri);
// 设置头信息
httppost.addHeader("Content-Type", "application/json");
httppost.addHeader("charset", HTTP.UTF_8);
try {
// 将参数进行json化
ObjectMapper mapper = new ObjectMapper();
String jsonStr = mapper.writeValueAsString(params);
Log.i(TAG, "URI=" + uri + ",BEAN=" + jsonStr);
// 定义消息实体
StringEntity se = new StringEntity(jsonStr, HTTP.UTF_8);
httppost.setEntity(se);
// 通信
HttpResponse resp = httpclient.execute(httppost);
int statusCode = resp.getStatusLine().getStatusCode();
Log.i(TAG, "StatusCode=" + statusCode);
if (statusCode == HttpStatus.SC_OK) {
StringBuffer result = getResponse(resp);
resultMsg = result.toString();
} else {
resultMsg = "连接异常";
}
} catch (Exception e) {
e.printStackTrace();
resultMsg = "连接异常";
} finally {
// 关闭get
httppost.abort();
// 关闭连接 ,释放资源
httpclient.getConnectionManager().shutdown();
}
Log.i(TAG, resultMsg);
return resultMsg;
}
二、SOCKET连接
服务器端:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class service_java_test {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(10000); //绑定的端口号
Socket socket = server.accept(); //连接不成功以至于下一行的"连接成功"
//在调试区显示不出来
System.out.println("连接成功");
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream());
while (true) {
String msg = in.readLine();
System.out.println(msg);
out.println("Server received " + msg); //向接收方发送已接受到了的语句
out.flush();
if (msg.equals("bye")) { //若接收到"bye"则break
break;
}
}
socket.close();
}
}
安卓客户端:
package com.example.t4_android;
import java.net.Socket;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends Activity {
private TextView myTextView;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myTextView = (TextView) findViewById(R.id.textView1);
Thread t = new Thread(new Runnable(){
public void run(){
try {
Socket sk = new Socket("192.168.253.1", 10000);//绑定套接字,这一行一直执行不成功
//以至于下一行在安卓页面的TextView上
//不显示“已连接”的字样
//"192.168.253.1"是我利用DOS命令查找
//的本机IP
myTextView.setText("已连接");
} catch (Exception e) {
e.printStackTrace();
}
}
});
t.start();
}
}