Android套接字编程

来源:互联网 发布:全国幼儿园名录数据库 编辑:程序博客网 时间:2024/05/17 20:29
第一步,使用本机和本机上Android模拟器通信,出现无法通信现象。原因是android的主ui线程不能执行一个工作线程,也就是执行网络操作之类的.
两种方法可以解决:
1\参考http://android.yyable.com/reference/android/os/StrictMode.html

2\删除androidmanifest.xml里的<uses-sdk android:minSdkVersion="14" />

也可以用其他方式处理,如handler。

开始以为是权限的问题。


android模拟器作为服务器端接收来自PC的UDP数据包,
需要在模拟器上做端口映射,用的命令跟TCP的时候有些不同
redir add udp:8000:9000
这样做了之后就可以收到UDP的包了!


创建线程有两种方法:继承Thread类和实现Runnable接口。方法一:继承 Thread 类,覆盖方法 run(),我们在创建的 Thread 类的子类中重写 run() ,加入线程所要执行的代码即可。下面是一个例子:
public class MyThread extends Thread {int count= 1, number;public MyThread(int num) {number = num;System.out.println("创建线程 " + number);}public void run() {while(true) {System.out.println("线程 " + number + ":计数 " + count);if(++count== 6) return;}}public static void main(String args[]) {for(int i = 0; i < 5; i++) new MyThread(i+1).start();}}

方法二:实现 Runnable 接口 Runnable 接口只有一个方法 run(),我们声明自己的类实现 Runnable 接口并提供这一方法,将我们的线程代码写入其中,就完成了这一部分的任务。但是 Runnable 接口并没有任何对线程的支持,我们还必须创建 Thread 类的实例,这一点通过 Thread 类的构造函数public Thread(Runnable target);来实现。下面是一个例子:
public class MyThread implements Runnable {int count= 1, number;public MyThread(int num) {number = num;System.out.println("创建线程 " + number);}public void run() {while(true) {System.out.println("线程 " + number + ":计数 " + count);if(++count== 6) return;} }public static void main(String args[]) {for(int i = 0; i < 5; i++) new Thread(new MyThread(i+1)).start();}}

Runnable说白了只是个回调接口,并不是所有的Runnable都是用于线程的;如果把它做为线程:传给Thread类传给Executor类



只要是关于UI相关的东西,就不能放在子线程中,因为子线程是不能操作UI的,只能进行数据、系统等其他非UI的操作。


1.要把Handle对象传递的东西放在一个消息循环的队列当中,如果没有这个消息循环队列的话,就会报错!

2.在做比较简单线程通讯的时候,我们只是在主Activity线程中使用Handler.sendMessage(Message)方法来实现消息的发送,用Handler.handleMessage(Message)类实现消息的获取,这似乎没有什么错误,而且如果在我们自己开启的普通线程中向主Activity线程发送消息似乎也不会有什么错误,可以捕获我们想要的消息。

3.但是如果我们接收消息的线程不在主线程那么而是一个普通线程,那么就会报错。为什么会这样呢?原因就是因为在我们自定义的普通线程中没有消息循环队列。那么怎么来实现一个消息循环队列呢?(假设我们都复写了handleMessage(Message)方法)

(1)这是最简单的方法,是在实例化Handler对象的时候传入调用HandlerThread.getLooper()获得的Looper对象,这个Looper就是我们需要的消息循环队列。当然这个HandlerThread对象必须调用start()方法去让他开启的线程运行。

(2)这个方法是模仿HandlerThread类的run()方法写出来的。就是在定义Handler对象的前加上Looper.prepare()方法,让消息循环开始准备,在定义完以后在调用Looper.loop();然消息循环开始运行。其实这两个方法本质上是没有没有区别的,都是给一个普通线程添加了一个消息队列。

4.那么为什么在Activity中就没有什么问题呢?

原因是Activity其实什么也不是,只是一个大怪物,他把很多功能都整合到了一起,并且把他封装起来,当然也包括一个消息循环队列(这个消息循环队列由系统来维护),所以在简单的主Activity中用Handler传递消息不会报错。有人说Activity是界面其实并不是这样的,我们看到的只不过是一个Window或者View,他用Window的功能监听事件,用View的功能显示界面,还有集成了数据存储等功能,等等。


通信代码:

 UDP通信实现:UDP使用DatagramSocket对象来实现 UDP的客户端代码实现如下:       public static void main(String[] args) {       try {           //首先创建一个DatagramSocket对象           DatagramSocket socket = new DatagramSocket(4567);           //创建一个InetAddreeInetAddress serverAddress = InetAddress.getByName("192.168.1.104");           String str = "hello";  //这是要传输的数据           byte data [] = str.getBytes();  //把传输内容分解成字节           //创建一个DatagramPacket对象,并指定要讲这个数据包发送到网络当中的哪个、地址,以及端口号           DatagramPacket packet = new DatagramPacket(data,data.length,serverAddress,4567);           //调用socket对象的send方法,发送数据           socket.send(packet);       } catch (Exception e) {           // TODO Auto-generated catch block           e.printStackTrace();       }}  UDP的服务端代码实现如下://创建一个DatagramSocket对象,并指定监听的端口号              DatagramSocket socket = new DatagramSocket(4567);              byte data [] = new byte[1024];              //创建一个空的DatagramPacket对象               DatagramPacket packet = new DatagramPacket(data,data.length);              //使用receive方法接收客户端所发送的数据,              //如果客户端没有发送数据,该进程就停滞在这里              socket.receive(packet);              String result = new String(packet.getData(),packet.getOffset(),packet.getLength());        System.out.println("result--->" + result); 5、  TCP通信的实现:TCP使用Socket对象 TCP协议客户端实现://创建一个Socket对象,指定服务器端的IP地址和端口号           Socket socket = new Socket("192.168.1.104",4567);           //使用InputStream读取硬盘上的文件           InputStream inputStream = new FileInputStream("f://file/words.txt");           //从Socket当中得到OutputStream           OutputStream outputStream = socket.getOutputStream();           byte buffer [] = new byte[4*1024];           int temp = 0 ;           //将InputStream当中的数据取出,并写入到OutputStream当中           while((temp = inputStream.read(buffer)) != -1){              outputStream.write(buffer, 0, temp);           }           outputStream.flush();       }    TCP协议服务器端现实:       //声明一个ServerSocket对象        ServerSocket serverSocket = null;        try {                //创建一个ServerSocket对象,并让这个Socket在4567端口监听              serverSocket = new ServerSocket(4567);        //调用ServerSocket的accept()方法,接受客户端所发送的请求,//如果客户端没有发送数据,那么该线程就停滞不继续              Socket socket = serverSocket.accept();              //从Socket当中得到InputStream对象              InputStream inputStream = socket.getInputStream();              byte buffer [] = new byte[1024*4];              int temp = 0;              //从InputStream当中读取客户端所发送的数据              while((temp = inputStream.read(buffer)) != -1){                  System.out.println(new String(buffer,0,temp));              }           } catch (IOException e) {              // TODO Auto-generated catch block              e.printStackTrace();           }            serverSocket.close();           }