用Unity打包Android程序并与PC端通过USB进行Socket通信(下)
这篇主要介绍一些简单代码,用程序打开ADB运行等,讲的稍微详细点,如果哪些地方用的不好,可以自己修改,这里只是给个思路。
按照上期流程,先开启ADB服务的连接,再开启Android端的服务,最后再开启PC上的端的程序作为客户端。由于每次手动打开win上的cmd或者linux上的终端比较麻烦,现在就用程序解决。以下都是使用C#写的程序。另外,需要稍微掌握一点linux知识,否则理解优点。
以下分三个部分:
一、在Windows中打开ADB方式
二、在Linux中两种打开ADB的方式
三、列出简单的TCP代码用于测试
一、在Windows中打开ADB
ADB属于外部程序,所有这里使用C#中的Process类。具体的可以看C#的官方文档。
C# Process 的官方描述
这个类主要是提供对本地和远程进程的访问,使你能够启动和停止本地系统进程。但是注意:需要开一个新的线程打开,否则会卡死主线程。
(1)在上期的手动配置打开时,使用的是win中的cmd,这里也可以用代码打开
private Thread processThread;
public void StartOpen()
{
processThread = new Thread(new ThreadStart(Start_Process_Win));
processThread.Start();
}
public void Start_Process_Win()
{
//下面是打开Process时,设置一个传入的process传入的参数
ProcessStartInfo info = new ProcessStartInfo("cmd.exe");//打开cmd的参数
info.CreateNoWindow = true;//不创建新的窗口
info.ErrorDialog = true;//错误日志
info.UseShellExecute = false;//使用shell
info.RedirectStandardError = true;
info.RedirectStandardInput = true;
info.RedirectStandardOutput = true;
m_Process = Process.Start(info);//创建并开启Process
//向cmd中输入参数
m_Process.StandardInput.WriteLine("E:");
m_Process.StandardInput.WriteLine("cd E:/ADB/platform-tools");
m_Process.StandardInput.WriteLine("adb start-server");
m_Process.StandardInput.WriteLine("adb forward tcp:13561 tcp:13562");
m_Process.StandardInput.WriteLine("exit");
m_Process.StandardInput.AutoFlush = true;
string output = m_Process.StandardOutput.ReadToEnd();
UnityEngine.Debug.Log(output);
string error = m_Process.StandardError.ReadToEnd();
UnityEngine.Debug.Log(error);
m_Process.WaitForExit();//等待退出打开的Process
m_Process.Close();//退出
}
上述通过打开cmd,再打开ADB似乎是一种特殊情况,因为中linux中是不能这样使用的。可以使用打开一次adb ,传入一次参数这种形式打开。在linux中测试是可以的,win中没有测试(因为懒),但想来也是可以的。下面提供简单的测试代码。
void OpenWithArguments()
{
//第一个参数是打开的外部程序,路径要对,第二个参数是打开外部程序时,传入的参数
Process.Start("E:/ADB/platform-tools/adb.exe", "start-server");
Process.Start("E:/ADB/platform-tools/adb.exe", "forward tcp:13561 tcp:13562");
}
二、在Linux中两种打开ADB的方式
(1)在linux中打开的方式也是类似的。也是要注意路径问题。还有一个要十分注意的地方是:如果想使用相对路径,你的程序使用的位置,是程序当前
void OpenWithArguments()
{
//第一个参数是打开的外部程序,路径要对,第二个参数是打开外部程序时,传入的参数
Process.Start("/ADB/platform-tools/adb.exe", "start-server");
Process.Start("/ADB/platform-tools/adb.exe", "forward tcp:13561 tcp:13562");
}
(2)这种方式是直接写一个shell文件,在你的C#程序中,直接用Process打开这个文件就可以了。可以在终端里输入:cat -n /etc/shells 看看可以兼容哪些shell程序。新建一个以.sh结尾的文件输入下列内容。
#!/etc/sh dir=$PWD #获取当前程序的执行路径 dir/platform-tools/adb start-server dir/platform-tools/adb forward tcp:13561 tcp:13562 exit
如果你把ADB工具放固定的位置,用绝对路径也可以。
如果用相对路径,那么,特别需要注意:脚本中$PWD 的路径是你的C#程序的路径,谁打开上述那个文件dir 就是那个位置的路径,使用时需要特别注意。
三、列出简单的TCP代码用于测试
这个是TCP连接中的客户端的部分代码,以前从网上抄的,但我找不到是抄谁的了(捂脸)。主要代码如下,也可以自己从网上找,参考一下。
public void Init(string ipStr, int port)
{
//连接到的目标IP
IPAddress ip = IPAddress.Parse(ipStr);
//连接到目标IP的哪个应用(端口号!)
IPEndPoint point = new IPEndPoint(ip, port);
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
//连接到服务器
client.Connect(point);
Debug.Log("连接成功,服务器IP:"+client.RemoteEndPoint.ToString());
Debug.Log("客户端IP:" + client.LocalEndPoint.ToString());
//连接成功后,就可以接收服务器发送的信息了
receiveThread = new Thread(ReceiveMsg);
IsWhile = true;
receiveThread.IsBackground = true;
receiveThread.Start();
}
catch (Exception ex)
{
Debug.LogError(ex.Message);
}
}
///
/// 收到消息
///
void ReceiveMsg()
{
while (IsWhile)
{
try
{
byte[] buffer = new byte[1024];
int n = client.Receive(buffer);
string str = Encoding.UTF8.GetString(buffer, 0, n);
if (!str.Equals(string.Empty))
{
//因为Unity非主线程,不能访问unity资源,把消息扔到一个队列中,在一个mono的Update中查看队列中有没有消息,有的话处理并给移除掉
lock (Message)
{
//GameEntry.Tcp.m_Message.Enqueue(str);
}
}
else
{
//如果大量 收到空消息,就说明服务端已经断开了,可以关闭本端口了
Debug.Log("net消息为空");
}
}
catch (Exception ex)
{
Debug.LogError(ex.Message);
break;
}
}
}
///
/// 发送消息到服务器
///
///
public void Send_To_Sever(string msg)
{
//客户端给服务器发消息
if (client != null)
{
try
{
//msg += (client.RemoteEndPoint + " | " + client.LocalEndPoint);
byte[] buffer = Encoding.UTF8.GetBytes(msg);
client.Send(buffer);
}
catch (Exception ex)
{
Debug.LogError(ex.Message);
}
}
}
TCP服务端的
//记录所有连接的Socket Dictionarydic=new Dictionary (); // private Socket client; private void StartServer(int port) { IPAddress ip = IPAddress.Any; //端口号 IPEndPoint point=new IPEndPoint(ip,port); //创建监听用的Socket //使用IPv4地址,流式socket方式,tcp协议传递数据 Socket socket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); //创建好socket后,必须告诉socket绑定的IP地址和端口号。 //让socket监听point try { //绑定监听的端口 socket.Bind(point); socket.Listen(10); Debug.Log("服务器开始监听"); Thread thread = new Thread(AcceptInfo); thread.IsBackground = true; thread.Start(socket); } catch (Exception ex) { Debug.Log(ex.Message); } } //开始接收连接 void AcceptInfo(object o) { Socket socket = o as Socket; while (true) { //通信用socket try { //创建通信用的Socket Socket tSocket = socket.Accept(); string point = tSocket.RemoteEndPoint.ToString(); //IPEndPoint endPoint = (IPEndPoint)client.RemoteEndPoint; Debug.Log(point + "连接成功!"); dic.Add(point, tSocket); //接收消息 Thread th = new Thread(ReceiveMsg); th.IsBackground = tr th.Start(tSocket); } catch (Exception ex) { Debug.Log(ex.Message); break; } } } //接收消息 void ReceiveMsg(object o) { Socket client = o as Socket; while (true) { //接收客户端发送过来的数据 try { //定义byte数组存放从客户端接收过来的数据 byte[] buffer = new byte[1024 * 1024]; //将接收过来的数据放到buffer中,并返回实际接受数据的长度 int n = client.Receive(buffer); //将字节转换成字符串 string words = Encoding.UTF8.GetString(buffer, 0, n); Debug.Log(client.RemoteEndPoint.ToString() + ":" + words); } catch (Exception ex) { Debug.Log(ex.Message); break; } } }



