PC经过USB链接Android通讯(Socket)

Android端Socket服务器java

/**
 * Created by Jack Stone on 2016/11/17.
 * Socket服务器,PC能够经过USB链接、ADB端口映射链接本服务器,不须要经过Wifi和网络
 */

public class TCPConnect implements Runnable {
    private static final String TAG = "TCPConnect";
    private final int SERVER_PORT = 10086;
    private ServerSocket mServerSocket;
    private Socket mClient;
    private Callback callback;

    public TCPConnect(Callback callback) {
        this.callback = callback;
    }


    @Override
    public void run() {
        try {
            String ip = InetAddress.getLocalHost().getHostAddress();
            mServerSocket = new ServerSocket(SERVER_PORT);
            callback.call("创建服务器:[" + ip + ":" + SERVER_PORT + "]");
        } catch (IOException e) {
            callback.call("创建服务器异常:" + e.getMessage());
        }
        while (true) {

            BufferedOutputStream out = null;
            BufferedReader in = null;
            try {
                mClient = mServerSocket.accept();
                callback.call("创建连接:" + mClient.getInetAddress().toString() + ":" + mClient.getPort());
                out = new BufferedOutputStream(mClient.getOutputStream());
                in = new BufferedReader(new InputStreamReader(mClient.getInputStream()));

                String request = receive(in);
                callback.call("client:"+request);
                send(out, request);

            } catch (IOException e) {
                Log.e(TAG, "run: ", e);
                callback.call(e.getMessage());
            } finally {
                close(out);
                close(in);
                close(mClient);
            }
        }
    }

    private void send(OutputStream out, String msg) throws IOException {
        msg += "\n";
        out.write(msg.getBytes("utf-8"));
    }

    private String receive(BufferedReader in) throws IOException {
        String r = in.readLine();
        callback.call("origin request:"+r);
        if(r.contains("\\&")) {
            callback.call("进行\\&替换!");
            r = r.replaceAll("\\\\&","\n");
        }
        return r;
    }

    private void close(OutputStream out) {
        if (out != null) {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void close(BufferedReader in) {
        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void close(Socket socket) {
        if (socket != null) {
            try {
                socket.close();
            } catch (IOException e) {
                Log.e(TAG, "run: ", e);
            }
        }
    }

    public interface Callback {
        void call(String msg);
    }
}

PC客户端

using CMDExecutor;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;

namespace AndroidUSBSocket
{
    public class SocketClient
    {
        public const string LOCAL_PORT = "12580";

        public SocketClient(string adb_path, string remote_port)
        {
            AdbExecutor adb = AdbExecutor.GetInstance(adb_path);
            adb.Forward(LOCAL_PORT, remote_port);
        }

        public string Request(string msg)
        {
            Socket client = null;
            try
            {
                client = create();
                connect(client, LOCAL_PORT);
                if (client.Connected)
                {
                    send(client, msg);
                    return receive(client);
                }
                else
                {
                    return "链接失败!";
                }
            }
            catch(Exception e)
            {
                return $"Error:{e.Message}";
            }
            finally
            {
                client.Shutdown(SocketShutdown.Both);
                client?.Close();
                Request(msg);
            }
        }

        private static void connect(Socket socket,string port)
        {
            IPAddress myIP = IPAddress.Parse("127.0.0.1");
            IPEndPoint EPhost = new IPEndPoint(myIP, int.Parse(port));
            socket.Connect(EPhost);     //create connection
        }

        private static Socket create()
        {
            return new Socket(
                    AddressFamily.InterNetwork,
                    SocketType.Stream,
                    ProtocolType.Tcp);
        }

        private static void send(Socket socket, string msg)
        {
            //request
            msg = msg.Replace("\n", "\\&");                 //replace all '\n' to '\&', those will be replace to '\n' when server received this msg
            msg += "\n";                                    //server is using readLine(), if not send a '\n' the stream won't push data to server
            byte[] data = Encoding.UTF8.GetBytes(msg);
            socket.Send(data);                              //send message to server
            //socket.Shutdown(SocketShutdown.Send);         //N-E-V-E-R close output stream, the socket will be closed together
            Debug.WriteLine($"发送完毕(长度[{msg.Length}] 字节[{data.Length}]):\n{msg}");
        }

        private static string receive(Socket socket)
        {
            //get response
            string str = "";
            byte[] data = new byte[10240];
            int len = 0;
            int i = 0;
            while ((i = socket.Receive(data)) != 0)         //read response string
            {
                len += i;
                string piece = Encoding.UTF8.GetString(data, 0, i);
                str += piece;
            }
            Debug.WriteLine($"接收完毕(长度[{str.Length}] 字节[{len}]):\n{str}");
            return str;
        }
    }
}



使用ADB进行端口的映射转发:adb forward tcp:local_port tcp:remote_port数组

SocketClient构造中的ADBExecutor就是用来执行这个命令的服务器


另外有一点不明白的是 SocketClient的receive方法中,byte[]的size我定的是10240网络

由于若是定小了,在获取字符串的过程当中就会由于这个尺寸不合适致使在边界上的字符变成???socket

C#不是很熟悉,这个地方不知道该怎么作,索性把size定得大一点,通常用不了这么长的字节数组tcp


使用这个方法要注意的是,只能经过PC主动向Android端发起请求,看了不少文档,貌似Android端是不能主动请求PC的,这个好像跟ADB的机制有关ide

可是ADB我并非理解得特别清楚,因此若是有大神知道如何让Android端主动请求PC端的服务器的话,但愿不吝赐教!this


有一个帖子说,Android经过USB链接电脑后,默认电脑的IP就是10.0.2.2,我试了一下,没啥成果,若是有人成功请联系我。spa


其余须要注意的地方在代码中的注释我都清楚地写出来了,欢迎交流。code