安卓socket实例(三)实现OPN,阿里+头条+腾讯等大厂Android面试题分享

import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

public class OPN extends BaseOperator {
public ArrayList exe(String cmdBody) throws Exception {
ArrayList backList=new ArrayList();
Desktop desk=Desktop.getDesktop();
File file=new File(cmdBody);//创建一个java文件系统
try {
desk.open(file); //调用open(File f)方法打开文件
backList.add(“成功运行文件:”+cmdBody);
} catch (IOException ex) {
ex.printStackTrace();
System.out.println(ex.toString());
backList.add(ex.toString());
}
return backList;
}
}

创建Operator.java负责处理传入的命令,调用指定函数类实现命令功能,并在获得功能类返回结果后在头部添加命令标签,为安卓端分析返回数据提供便捷。

package lrz.tool;

import lrz.data.DIR;
import lrz.data.OPN;
import java.util.ArrayList;

public class Operator {
public static ArrayList exeCmd(String cmd) throws Exception {
//所有的命令操作在此静态函数中判断及调用返回
//后续新增的命令判断操作在此函数中添加
String[] splitCmd = splitCmd(cmd);//按":"分割命令
// 分割时,会把命令前缀转为小写,以保证判断不分大小写
String cmdHead = splitCmd[0];
String cmdBody = splitCmd[1];

ArrayList msgBackList = new ArrayList();

if (cmdHead.equals(“dir”)) {
msgBackList = new DIR().exe(cmdBody);
msgBackList.add(0,“dir”);//增加正常执行返回的代码"ok"
return msgBackList;
}
if (cmdHead.equals(“opn”)) {
msgBackList = new OPN().exe(cmdBody); // 待实现的打开文件命令
msgBackList.add(0,“opn”);//增加正常执行返回的代码"ok"
return msgBackList;
}
//… 继续判断其他命令

if(msgBackList.size()==0){
msgBackList.add(0,“无效命令:”+cmd);//msgBackList长度为0,说明命令没有得到解析和执行
}

throw new Exception(“无效命令!”);//若代码正确执行了,就return了,不会执行到这里,执行到这说明出错了
}

public static String[] splitCmd(String cmd) throws Exception {
String[] cmdout = null;
int splitIdx = cmd.indexOf("😊;
System.out.println("服务端接受命令: " + cmd);
if (splitIdx < 1) {
throw new Exception("非法命令: " + cmd);// 抛出异常
} else {
cmdout = new String[2];
String cmdHead = cmd.substring(0, splitIdx);
String cmdBody = cmd.substring(splitIdx + 1);
cmdout[0] = cmdHead.toLowerCase();//按小写处理字符串
cmdout[1] = cmdBody;
}
return cmdout;

}
}

ServerSocket01.java更改如下

package lrz.server;

import lrz.tool.Operator;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Enumeration;

public class ServerSocket01 {

int port = 8019;// 自定义一个端口,端口号尽可能挑选一些不被其他服务占用的端口,祥见http://blog.csdn.net/hsj521li/article/

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享

details/7678880
ArrayList msgBackList;

public ServerSocket01() {
// TODO Auto-generated constructor stub
}

public ServerSocket01(int port) {
super();
this.port = port;
}
private void printLocalIp(ServerSocket serverSocket) {// 枚举打印服务端的IP
try {
System.out.println(“服务端命令端口prot=” + serverSocket.getLocalPort());
Enumeration interfaces = null;
interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface ni = interfaces.nextElement();
Enumeration addresss = ni.getInetAddresses();
while (addresss.hasMoreElements()) {
InetAddress nextElement = addresss.nextElement();
String hostAddress = nextElement.getHostAddress();
System.out.println(“本机IP地址为:” + hostAddress);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}

public void work() throws Exception {
// 注意:由于Socket的工作是阻塞式,Android端Socket的工作必须在新的线程中实现,若在UI主线程中工作会报错
ServerSocket serverSocket = new ServerSocket(port);
printLocalIp(serverSocket);

while (true) {// 无限循环
System.out.println("=");
System.out.println("| Waiting client to connect…|");
System.out.println("
=");

Socket socket = serverSocket.accept();// 阻塞式
System.out.println("连接请求来自: "+ socket.getRemoteSocketAddress().toString());
try{
getAndDealCmd(socket);
} catch (Exception e) {
cmdFail(e.toString());
}
SocketMsg.writeBackMsg(socket,msgBackList);

System.out.println("…输出流…");
msgBackList.forEach(s -> System.out.println(s));
System.out.println("…");

socket.close();
System.out.println(“本次Socket服务结束”);
System.out.println("---------------------------------");
System.out.println("---------------------------------");

}

}

public void getAndDealCmd(Socket socket) throws Exception {

ArrayList cmdList = SocketMsg.readSocketMsg(socket);
if(cmdList.size()==0){
cmdFail(“Cmd输入为空. “);//若命令长度0行,则返回错误信息
}
System.out.println(”…输入流…”);
cmdList.forEach(s -> System.out.println(s));
System.out.println("…");

if(cmdList.size()==1){
msgBackList=Operator.exeCmd(cmdList.get(0));// Operator类为自定义类,实现命令头部和主体的分离和调用判断
}else{
// msgBackList=MultiOperator.exeCmd(cmdList);//待实现的,支持多条命令串行执行
}

}

private void cmdFail(String e) {
msgBackList.clear();//
String nu=“java.lang.NullPointerException”;
if(e.equals(nu)){
e=“目标不存在”;
}
msgBackList.add(e);//将出错信息放入msgBackList
}

/**

  • @param args
    */
    public static void main(String[] args) throws Exception {
    new ServerSocket01().work();
    }

}

安卓端更新

SocketClient.java添加对服务端返回命令头部命令类型的解析,设置handler返回的type,例如SERVER_MSG_DIR,借此在MainActivity.java得以让handler监听到的数据根据不同的命令返回结果进行不同的操作。

package com.example.android_app;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;

public class SocketClient {
public static int SERVER_MSG_OK=0;//用于发送给句柄的消息类型,放在消息的arg2中,表示服务端正常
public static int SERVER_MSG_ERROR=1;//表示服务端出错
public static int SERVER_MSG_DIR=2;//表示DIR操作返回
public static int SERVER_MSG_OPN=3;//表示OPN操作返回
private int msgType;
private String ip;
private int port;
private int connect_timeout=10000;
private Handler handler;
private Socket socket;
public static final String KEY_SERVER_ACK_MSG = “KEY_SERVER_ACK_MSG”;
private OutputStreamWriter writer;
private BufferedReader bufferedReader;
public SocketClient(String ip, int port, Handler handler) {
this.port = port;
this.ip = ip;
this.handler = handler;
}

private void connect() throws IOException {//连接服务端函数
InetSocketAddress address = new InetSocketAddress(ip, port);
socket = new Socket();
socket.connect(address, connect_timeout);
}
private void writeCmd(String cmd) throws IOException {
BufferedOutputStream os=new BufferedOutputStream(socket.getOutputStream());
writer=new OutputStreamWriter(os,“UTF-8”);
writer.write(“1\n”);
writer.write(cmd+"\n");
writer.flush();
}
private ArrayList readSocketMsg() throws IOException {
ArrayList msgList=new ArrayList<>();
InputStreamReader isr=new InputStreamReader(socket.getInputStream(),“UTF-8”);
bufferedReader=new BufferedReader(isr);
String numStr = bufferedReader.readLine();
int linNum = Integer.parseInt(numStr);
msgType=SERVER_MSG_ERROR;
if(linNum<1){
msgList.add(“服务端返回为空”);
return msgList;
}
String status = bufferedReader.readLine();
if(status.equalsIgnoreCase(“OK”)){
msgType=SERVER_MSG_OK;
}else if(status.equalsIgnoreCase(“DIR”)){
msgType=SERVER_MSG_DIR;
}else if(status.equalsIgnoreCase(“OPN”)){
msgType=SERVER_MSG_OPN;
}else{
msgList.add(status);//将服务端的错误信息放入消息列表
}
for (int i = 1; i <linNum ; i++) {
String s = bufferedReader.readLine();
msgList.add(s);
}
return msgList;
}
private void close() throws IOException {
bufferedReader.close();
writer.close();
socket.close();
}
private void doCmdTask(String cmd){
ArrayList msgList=new ArrayList<>();
try {
connect();
writeCmd(cmd);
msgList = readSocketMsg();
close();
} catch (IOException e) {
msgType=SERVER_MSG_ERROR;
msgList.add(e.toString());
e.printStackTrace();
}
Message message = handler.obtainMessage();
Bundle bundle = new Bundle();
bundle.putStringArrayList(KEY_SERVER_ACK_MSG,msgList);
message.arg2=msgType;
message.setData(bundle);
handler.sendMessage(message);

}
public void work(final String cmd){
new Thread(new Runnable() {
@Override
public void run() {
doCmdTask(cmd);
}
}).start();
}
}

Activity_main.xml添加一个textview来显示操作信息

<?xml version="1.0" encoding="utf-8"?>



MainActivity.java更改如下,添加handler对不同返回type的判定与不同操作,并且将操作结果显示在一个Textview中

package com.example.android_app;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import androidx.annotation.NonNull;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值