已上传GitHub,包括源码及aix,以及测试用aia,顺便贴个apk上去。
国内可以访问Gitee,来自开学后虚脱的我。。。
Wifi下通信应该是大家都希望的吧,网上TaifunWiFi似乎很高级的样子,但是原谅我英语渣,看不懂。。。
mac和ip我懂,可是ssid是神马。。。看来我tcp/ip还没啃到家。。。
TaifunWiFi盯了半天似乎好像大概可能应该差不多是怎么去连接WiFi而不是通信的。
好像很多人的需求是和arduino有关,谁能来介绍一下,不懂
Android下很多人都讲了怎么用socket通信,可是移植到app inventor上的很少。
那就让我来开心的皮一下,介绍一下怎么在局域网内通信,不止WiFi哦。
我就不扯tcp/ip了,估计也没人有心思听。
这里只是讲一些基础知识,因为这个插件目前只能传字符串,如果要更多功能就需要自行补充了。
两台计算机间进行通讯需要以下三个条件
:IP地址、协议、端口号。IP地址
肯定听说过,用人话说就像一个港口。端口号
用于区分一台主机的多个不同应用程序,范围为0-65535,我取8000,0-1023为为系统保留。用人话讲就像港口有很多船位,可以同时停很多条船。Socket
由IP地址+端口号组成。在Java中是使用TCP协议实现的网络通信。ServerSocket
是服务端。
因为网络连接是一个非常耗时的操作,比读写硬盘还耗时,需要单独一个线程,甚至不止一个。
Client客户端状态良好,可发,收等会再说
Sever服务端莫名智障,打电话也不接,发短信也不回,最后发现是message是直接new的,要从myHandler.obtainMessage()获取才有用,坑死我了。。。
又被这个message坑了一回,每次sendMessage都要重新获取message一回,或者相邻几行不用,我也没搞懂,反正每次sendMessage都获取一遍问题就解决了,不然闪退,连个报错都没有,连接adb才得到错误信息,坑啊
Sever服务端测试成功!
等我重写一下,达到能够使用的程度。
又是一个坑,OutputStream的flush()是个空方法,只能再建一个BufferedOutputStream。
readline结尾要加\n!不是OutputStream的问题,这是装饰模式,空方法就是用于覆盖。
测试完成,鉴定可食用。
全文见SocketUtil.java
收到消息的回调,顺便加了个回车
@SimpleEvent public void GetMessage(String s){ EventDispatcher.dispatchEvent(this, 'GetMessage', '\n'+s);}
- 1
- 2
- 3
handler用于从子进程返回UI线程,并调用回调。
如果你需要区分不同的消息的话,设置what,在handler里if-else或switch都可以。
public Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { /*switch(msg.what){ case 1:...break; }*/ GetMessage(msg.obj.toString()); }};/*Message message_1 = handler.obtainMessage();message_1.what= 11;message_1.obj = '';handler.sendMessage(message_1);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
获得ip以及port的代码
String ip;int port;private ServerSocket serverSocket = null;public void getLocalIpAddress(ServerSocket serverSocket){ try { for (Enumeration<NetworkInterface> en=NetworkInterface.getNetworkInterfaces();en.hasMoreElements();){ NetworkInterface intf = en.nextElement(); for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses();enumIpAddr.hasMoreElements();){ InetAddress inetAddress = enumIpAddr.nextElement(); String mIP = inetAddress.getHostAddress().substring(0, 3); if(mIP.equals('192')){ ip = inetAddress.getHostAddress(); //获取本地IP port = serverSocket.getLocalPort(); } } } } catch (SocketException e) {}}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
内部类,用于读取数据直到换行符,就是新的设备连接时的消息处理类
class ServerThread extends Thread{ Socket socket; Message message_2; public ServerThread(Socket socket){ this.socket = socket; } @Override public void run() { try { BufferedReader br = null; br = new BufferedReader(new InputStreamReader(socket.getInputStream())); while(true){ String msg = null; msg = br.readLine(); if(msg != null){ message_2 = handler.obtainMessage(); message_2.obj = socket.getInetAddress().getHostAddress()+':'+msg;//把ip和冒号拼到消息上 handler.sendMessage(message_2); } } } catch (IOException e) { message_2 = handler.obtainMessage(); message_2.obj = '他好像不见了'; handler.sendMessage(message_2); try{socket.close();}catch(Exception e1){} } } }
- 1
- 2
- 3
- 4
- 5
- 6
- 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
启动服务的方法
@SimpleFunction public void receiveData(){ Thread thread = new Thread(){ @Override public void run() { //.. } }; thread.start();}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
端口8000,初始化ip和port,发送一个message
try { serverSocket = new ServerSocket(8000);} catch (IOException e) { e.printStackTrace();}getLocalIpAddress(serverSocket);Message message_1 = handler.obtainMessage();message_1.obj = 'IP:' + ip + ' PORT: ' + port;handler.sendMessage(message_1);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
如果有新的设备连接,新建一个线程用于接收
while (true){ Socket socket = null; try { socket = serverSocket.accept();//如果没有设备连接会阻塞在这一句 //如果想控制连接数就把while改成for,然后计数即可 Message message_2 = handler.obtainMessage(); message_2.obj = '有兄弟连上了!'+socket.getInetAddress().getHostAddress(); handler.sendMessage(message_2); catch (IOException e) {} new ServerThread(socket).start();}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
全文见SocketClient.java
handle等服务端出现的就不再叙述
这仨函数也没必要介绍了,一看就明白,重点在于那个线程
Socket socket = null;MyThread mt;final int CONNECT = 100001;final int SENDMESSAGE = 100002;final int CLOSE = 100003;@SimpleFunction(description = 'start')//关闭链接public void closeConnect(){ if(socket != null){ mt = new MyThread(CLOSE); mt.start(); }else{ GetMessage('连接未创建!'); }}//发送消息@SimpleFunction(description = 'start')public void sendMessage(String s){ if(socket != null){ mt = new MyThread(SENDMESSAGE); mt.setText(s); mt.start(); }else{ GetMessage('连接未创建!'); }}//连接@SimpleFunction(description = 'start')public void connect(String ip){ if(socket == null){ mt = new MyThread(CONNECT); mt.setIP(ip); mt.start(); }else{ GetMessage('连接已创建!'); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 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
额因为懒得写三个类所以合起来了
class MyThread extends Thread { public String txt1; public String IP; Message msg; public int flag; public MyThread(int flag) {this.flag = flag; } public void setText(String s){txt1 = s;} public void setIP(String ip){IP = ip;} @Override public void run() { switch(flag){ case CONNECT: //连接... break; case SENDMESSAGE //发送... break; case CLOSE: //关闭... break; } } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
连接
case CONNECT: try { socket = new Socket(); msg = myHandler.obtainMessage(); msg.obj = '开始连接'; myHandler.sendMessage(msg); socket.connect(new InetSocketAddress(IP, 8000), 1000);//端口8000,超时1000ms ou = socket.getOutputStream();//获取输出流 msg = myHandler.obtainMessage(); msg.obj = '连接成功'; myHandler.sendMessage(msg); } catch (SocketTimeoutException aa) { msg = myHandler.obtainMessage(); msg.obj = '连接超时'; myHandler.sendMessage(msg); socket = null; } catch (IOException e) { msg = myHandler.obtainMessage(); msg.obj = '未知错误'; myHandler.sendMessage(msg); socket = null; }break;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
发信
case SENDMESSAGE: try { ou.write(txt1.getBytes('utf-8'));//用utf8输出字符串,一定要化成字节流 ou.write('\n'.getBytes('utf-8'));//因为是读取一行,一行结束了要加换行 ou.flush();//清空缓冲区 msg = myHandler.obtainMessage(); msg.obj = '发送完毕'; myHandler.sendMessage(msg); }catch (IOException e) { msg = myHandler.obtainMessage(); msg.obj = '未知错误'; myHandler.sendMessage(msg); }break;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
关闭
case CLOSE: try { ou.close(); socket.close(); socket = null; msg = myHandler.obtainMessage(); msg.obj = '关闭'; myHandler.sendMessage(msg); }catch (IOException e) { msg = myHandler.obtainMessage(); msg.obj = '未知错误'; myHandler.sendMessage(msg); }break;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
难得我终于发测试图了。。。
不过一个问题,就是要测试的话需要两个手机,我翻箱倒柜找到了一个特别卡的旧手机,所以截图只能在那个比较新的手机上完成
所以我用那个新手机分别做了一次client和server,分别截图
还有,server只能打开一次,第二次会闪退,要彻底关掉才能打开第二次
发现一个很神奇的事,电脑热点共享后竟然可以直连,但只能单向
server服务端长这样
联系客服