logo资料库

PC客户端与Android服务端的Socket同步通信.docx

第1页 / 共26页
第2页 / 共26页
第3页 / 共26页
第4页 / 共26页
第5页 / 共26页
第6页 / 共26页
第7页 / 共26页
第8页 / 共26页
资料共26页,剩余部分请下载后查看
http://blog.csdn.net/wufenglong/article/details/5778862 PC 客户端与 Android 服务端的 Socket 同步通信(USB) 分类: android 2010-07-31 17:23 8027 人阅读 评论(52) 收藏 举报 需求: 1.一个 android 端的 service 后台运行的程序,作为 socket 的服务器端;用于接收 Pc client 端发来的命令,来处理 数据后,把结果发给 PC client 2.PC 端程序,作为 socket 的客户端,用于给 android 手机端发操作命令 难点分析: 1.手机一定要有 adb 模式,即插上 USB 线时马上提示的对话框选 adb。好多对手机的操作都可以用 adb 直接作。 不过,我发现 LG GW880 就没有,要去下载个 2.android 默认手机端的 IP 为“127.0.0.1” 3.要想联通 PC 与 android 手机的 sokcet,一定要用 adb forward 来作下端口转发才能连上 socket. view plaincopy to clipboardprint? 1. Runtime.getRuntime().exec("adb forward tcp:12580 tcp:10086"); 2. Thread.sleep(3000); Runtime.getRuntime().exec("adb forward tcp:12580 tc Thread.sleep(3000); 4.android 端的 service 程序 Install 到手机上容易,但是还要有方法来从 PC 的 client 端来启动手机上的 service ,这个办法可以通过 PC 端 adb 命令来发一个 Broastcast ,手机端再写个接收 BroastcastReceive 来接收这个 Broastcast,在这个 BroastcastReceive 来启动 service
pc 端命令: view plaincopy to clipboardprint? 1. Runtime.getRuntime().exec( 2. "adb shell am broadcast -a NotifyServiceStart"); Runtime.getRuntime().exec( "adb shell am broadcast -a NotifyServiceStart"); android 端的代码:ServiceBroadcastReceiver.java view plaincopy to clipboardprint? 1. package com.otheri.service; 2. 3. import android.content.BroadcastReceiver; 4. import android.content.Context; 5. import android.content.Intent; 6. import android.util.Log; 7. 8. public class ServiceBroadcastReceiver extends BroadcastReceiver { 9. 10. 11. 12. 13. 14. private static String START_ACTION = "NotifyServiceStart"; private static String STOP_ACTION = "NotifyServiceStop"; @Override public void onReceive(Context context, Intent intent) { Log.d(androidService.TAG, Thread.currentThread().getName() + "---->"
+ "ServiceBroadcastReceiver onReceive"); String action = intent.getAction(); if (START_ACTION.equalsIgnoreCase(action)) { context.startService(new Intent(context, androidService.class)); Log.d(androidService.TAG, Thread.currentThread().getName() + "---->" + "ServiceBroadcastReceiver onReceive start end"); } else if (STOP_ACTION.equalsIgnoreCase(action)) { context.stopService(new Intent(context, androidService.class)); Log.d(androidService.TAG, Thread.currentThread().getName() + "---->" + "ServiceBroadcastReceiver onReceive stop end"); } } 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. } package com.otheri.service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; public class ServiceBroadcastReceiver extends Broad private static String START_ACTION = "Notif private static String STOP_ACTION = "Notify @Override public void onReceive(Context context, Inte Log.d(androidService.TAG, Thread.cu + "ServiceBroadcast String action = intent.getAction(); if (START_ACTION.equalsIgnoreCase(a 5.由于是 USB 连接,所以 socket 就可以设计为一但连接就一直联通,即在 new socket 和开完 out,in 流后,就用个 while(true){}来循环 PC 端和 android 端的读和写 android 的代码: view plaincopy to clipboardprint? 1. public void run() { 2. 3. 4. 5. 6. Log.d(androidService.TAG, Thread.currentThread().getName() + "---->" + "a client has connected to server!"); BufferedOutputStream out; BufferedInputStream in; try {
7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. /* PC 端发来的数据 msg */ String currCMD = ""; out = new BufferedOutputStream(client.getOutputStream()); in = new BufferedInputStream(client.getInputStream()); // testSocket();// 测试 socket 方法 androidService.ioThreadFlag = true; while (androidService.ioThreadFlag) { try { if (!client.isConnected()) { break; } /* 接收 PC 发来的数据 */ Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "will read......"); /* 读操作命令 */ currCMD = readCMDFromSocket(in); Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "**currCMD ==== " + currCMD); /* 根据命令分别处理数据 */ if (currCMD.equals("1")) { out.write("OK".getBytes()); out.flush(); } else if (currCMD.equals("2")) { out.write("OK".getBytes()); out.flush(); } else if (currCMD.equals("3")) { out.write("OK".getBytes()); out.flush(); } else if (currCMD.equals("4")) { /* 准备接收文件数据 */ try { out.write("service receive OK".getBytes()); out.flush(); } catch (IOException e) { e.printStackTrace(); } /* 接收文件数据,4 字节文件长度,4 字节文件格式,其后是文件数据 */
47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. byte[] filelength = new byte[4]; byte[] fileformat = new byte[4]; byte[] filebytes = null; /* 从 socket 流中读取完整文件数据 */ filebytes = receiveFileFromSocket(in, out, filelength, fileformat); // Log.v(Service139.TAG, "receive data =" + new // String(filebytes)); try { /* 生成文件 */ File file = FileHelper.newFile("R0013340.JPG"); FileHelper.writeFile(file, filebytes, 0, filebytes.length); } catch (IOException e) { e.printStackTrace(); } } else if (currCMD.equals("exit")) { } } catch (Exception e) { // try { // out.write("error".getBytes("utf-8")); // out.flush(); // } catch (IOException e1) { // e1.printStackTrace(); // } Log.e(androidService.TAG, Thread.currentThread().getName() + "---->" + "read write error111111"); } } out.close(); in.close(); } catch (Exception e) { Log.e(androidService.TAG, Thread.currentThread().getName() + "---->" + "read write error222222"); e.printStackTrace(); } finally { try {
87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. if (client != null) { Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "client.close()"); client.close(); } } catch (IOException e) { Log.e(androidService.TAG, Thread.currentThread().getName() + "---->" + "read write error333333"); e.printStackTrace(); } } public void run() { Log.d(androidService.TAG, Thread.cu + "a client has con BufferedOutputStream out; BufferedInputStream in; try { /* PC端发来的数据msg */ String currCMD = ""; out = new BufferedOutputStr in = new BufferedInputStrea // testSocket();// 测试sock androidService.ioThreadFlag while (androidService.ioThr try { if (!client bre } 6.如果是在 PC 端和 android 端的读写操作来 while(true){}循环,这样 socket 流的结尾不好判断,不能用“-1”来判断, 因为“-1”是只有在 socket 关闭时才作为判断结尾。 7.socket 在 out.write(bytes);时,要是数据太大时,超过 socket 的缓存,socket 自动分包发送,所以对方就一定要用 循环来多次读。最好的办法就是服务器和客户端协议好,比如发文件时,先写过来一个要发送的文件的大小,然后再 发送文件;对方用这个大小,来循环读取数据。 android 端接收数据的代码: view plaincopy to clipboardprint? 1. /** 2. 3. 4. 5. 6. 7. 8. 9. * 功能:从 socket 流中读取完整文件数据 * * InputStream in:socket 输入流 * * byte[] filelength: 流的前 4 个字节存储要转送的文件的字节数 * * byte[] fileformat:流的前 5-8 字节存储要转送的文件的格式(如.apk) *
10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. * */ public static byte[] receiveFileFromSocket(InputStream in, OutputStream out, byte[] filelength, byte[] fileformat) { byte[] filebytes = null;// 文件数据 try { int filelen = MyUtil.bytesToInt(filelength);// 文件长度从 4 字节 byte[]转成 Int String strtmp = "read file length ok:" + filelen; out.write(strtmp.getBytes("utf-8")); out.flush(); filebytes = new byte[filelen]; int pos = 0; int rcvLen = 0; while ((rcvLen = in.read(filebytes, pos, filelen - pos)) > 0) { pos += rcvLen; } Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "read file OK:file size=" + filebytes.length); out.write("read file ok".getBytes("utf-8")); out.flush(); } catch (Exception e) { Log.v(androidService.TAG, Thread.currentThread().getName() + "---->" + "receiveFileFromSocket error"); e.printStackTrace(); } return filebytes; } /** * 功能:从socket流中读取完整文件数据 * * InputStream in:socket输入流 * * byte[] filelength: 流的前4个字节存储要转送 * * byte[] fileformat:流的前5-8字节存储要转送 * * */ public static byte[] receiveFileFromSocket( OutputStream out, byte[] fi byte[] filebytes = null;// 文件数据 try { int filelen = MyUtil.bytesT String strtmp = "read file out.write(strtmp.getBytes(" out.flush(); 8.socket 的最重要的机制就是读写采用的是阻塞的方式,如果客户端作为命令发起者,服务器端作为接收者的话,只 有当客户端 client 用 out.writer()写到输出流里后,即流中有数据 service 的 read 才会执行,不然就会一直停在 read() 那里等数据。
9.还要让服务器端可以同时连接多个 client,即服务器端用 new thread()来作数据读取操作。 源码: 客户端(pc 端): testPcClient.java view plaincopy to clipboardprint? 1. import java.io.BufferedInputStream; 2. import java.io.BufferedOutputStream; 3. import java.io.BufferedReader; 4. import java.io.ByteArrayOutputStream; 5. import java.io.IOException; 6. import java.io.InputStream; 7. import java.io.InputStreamReader; 8. import java.net.InetAddress; 9. import java.net.Socket; 10. import java.net.UnknownHostException; 11. 12. public class testPcClient { 13. 14. 15. 16. 17. 18. 19. 20. 21. /** * @param args * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { try { Runtime.getRuntime().exec( "adb shell am broadcast -a NotifyServiceStop");
分享到:
收藏