最近做了一个十分有意思的项目,功能是网页和android的各种数据通信交互,刚到手的时候直线碾压了我这个小菜。功夫不负苦心人,在问遍了身边前端,服务器开发人员之后,终于搞定了,不由洒出一些心酸泪。
言归正传,流程需求如下:
1. 加载指定网页;
2. 监听指定端口9999;
3. 获取访问数据;
4. 回复指定数据;
网页的核心代码如下:
<script>
$(function(){
$.ajax({
url : 'http://127.0.0.1:9999/android/login',
type: 'get',
dataType : 'jsonp',
jsonp : 'callback'
data:{'mac':'00:00:00:00:00'},
success: function(response){
alert(response);
},
error: function(){
alert("error")
}
});
});
</script>
学过jQuery的同学都懂这个是什么,是利用jQuery的库,向服务端:
http://127/0.0.1:9999/android/login 发送一个get请求,并携带参数:
mac=00:00:00:00:00 等待回应。请求成功后输出相应内容,失败弹窗提示
学过jQuery的同学都懂这个是什么,是利用jQuery的库,向服务端:http://127.0.0.1:9999/android/login发送一个get请求,并携带参数mac=00:00:00:00:00,等待回应,请求成功输出响应内容,失败弹窗提示。
于是建立代码:
public class LoginActivity extends AppCompatActivity
private ServerSocket ss;
private Socket mSocket;
private InputStream mStream;
private BufferedReader mReader;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startServer();
mEditText = (EditText)findViewById(R.id.main_et_msg);
}
public void startServer(){
new Thread(){
@Override
public void run(){
connection();
}
}.start();
}
public void connectClient(){
ss = new ServerSocket(9999);
while(true){
try{
mSocket = ss.accept();
mStream = socket.getInputStream();
mReader = new BufferedReader(new InputStreamReader(mStream));
String request = mReader.readLine();
if(request.contains("mac")){
Message msg = mHandler.obtainMessage();
msg.obj = request;
msg.arg0 = 200;
mHandler.sendMessage(msg);
break;
}else{
socket.close;
}
}catch(Exception e){
e.printStackTrace();
}
}
}
public void responseClient(View view){
if(mSocket = null || !mSocket.isConnected()){
<span style="white-space:pre"> </span>return;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>String msg = "{\"rsponse\":"login"}";
OutputStream out = mSocket.getOutputStream();
out.write(msg.getBytes());
out.flush();
out.close();
mReader.close();
mStream().close();
mSocket.close();
ss.close();
}
@Override
protected void onDestroy() {
super.onDestroy();
mSocket.close();
}
}
界面一启动,立马创建一个9999端口的服务端,但凡通过端口请求的client都可以响应到我们开启的端口服务端,并获取数据和相应数据。
然而问题来了,回复相应内容并没有让客户端获得回应。刚开始令我百思不得其解,后来一位服务端的大神告诉我,请求头里面还有一个隐藏的信息:callback。
经过询问,大概是这个意思,callback也是http请求携带的参数,代表回调请求的方法,一般参数值为:
jQuery1111111... ,必须要返回给请求对象确保js响应。
所以我们服务端响应的数据就不能只是简单的回复一个response=“login”的json字符串,而应该是jQuery能够响应的方法事件。
于是我们应该先获取callback的参数内容。
private String mCallBack;
private Handler mHandler = new Handler(){
<span style="white-space:pre"> </span>@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch(msg.arg0){
case 200:
mCallBack = parser((String)msg.obj);
break;
default:
break;
}
}
};
然后我们就可以回复客户端:mCallBack + "({\"response\:\"\login"\"})" 这样一串数据就能够完美的执行动作了。
不过这里还有一个疑问,/android/login这个地址对我们到底有没有作用?
国外有一个人写了一个叫做NanoHttpD的java文件,将ServerSocket进行更深层次的封装,通过这种方式,甚至可以像http请求一样通过方法获取指定参数、url、等等。。。
使用方法也很简单,通过
NanoHttpD nanoHttpD = new NanoHttpD(9999,new File(Environment.getExternalStorageDirectory().getPath(),"android/login"));
就可以启动服务端了,在退出应用的时候别忘了nanoHttpD.stop();
附参考链接: