转载

Android udp 广播发送和接收

最近在和同学开发一款app,作为课程大作业。其中,涉及到udp socket (多播) 的发送和接收、tcp socket 的发送和接收。作为一个Java的门外汉,在简单地看了一些理论地资料之后,实际编程中遇到了不少问题。然后,又在网上大搜这方面的博客,找来找去,其实大家写的东西基本都一样,因为规则已经订好了。网上的代码不全,又有一些错漏,让我走了很多弯路,无数次推倒代码重写,debug,终于调出了一个实际可运行的版本。 希望初学的童鞋看到我的这篇博客能少走一些弯路.

-----------------------

转载请注明出处:

http://www.cnblogs.com/zhangzph/p/4475962.html

-----------------------

在给出代码之前,先简单介绍一下我的代码在做什么。

代码逻辑:

本机发送udp广播

本机开启线程,监听来自别的机器的udp广播,显示信息。 然后,对udp来源发送tcp连接

接收来自别的机器的tcp连接,并显示信息

(这里的udp广播,我使用udp多播代替了,多播具有广播的所有优点,而且有更少的缺点,实现上也比较简单,这里就不再过多地介绍了)

具体ui操作:

Android udp 广播发送和接收

start 按钮用来启动udp 多播,stop按钮停止发送 (实际上,由于start 按钮按下之后只发送一次udp多播,stop按钮只是用于setEnabled操作)下面有两个TextView,内容为send的TextView 显示--本机发送 tcp socket 的信息; 内容为receive的TextView 显示--本机接收来自别的机器的udp socket 和 tcp socket 的信息.

几个需要注意的地方:

1. Android Manifest 权限设置、sdk版本信息:

本文所涉及到的这些功能需要获取 Android 的一些权限,下面是我的权限和版本信息

<uses-sdk  android:minSdkVersion="15"  android:targetSdkVersion="21" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/> 

上面 条目 uses-sdk中的信息,需要在build.gradle文件中同步。

Android udp 广播发送和接收

2. 注意udp广播,和udp广播监听需要绑定同一个端口

3. 其他的有关IDE抽风的问题,比如我的Android Studio,有时候你修改了代码,重新把程序烧进手机的时候,它竟然会用缓存中代码的老版本来烧程序。。。 还有,有时候project加载太慢,程序崩溃之后,logcat好长时间都不出错误信息,严重影响debug。

4. 建议使用android sdk版本比较新的手机进行测试。 我测试的时候,用一部4.4和5.1的成功了。混合另外一部4.0.x的则有时候不太灵通。

github上的项目链接:

https://github.com/zhangpzh/Anjay

主要代码:

xml 源码:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  xmlns:tools="http://schemas.android.com/tools"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:orientation="vertical"  tools:context=".MyActivity">  <LinearLayout   android:layout_width="match_parent"   android:layout_height="wrap_content"   android:orientation="horizontal"   android:gravity="center_horizontal"   >   <Button    android:id="@+id/start"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:text="start"    />   <Button    android:id="@+id/stop"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:layout_marginLeft="150dp"    android:text="stop"    />  </LinearLayout>  <LinearLayout   android:layout_width="match_parent"   android:layout_height="wrap_content"   android:orientation="horizontal"   android:gravity="center_horizontal"   >   <TextView    android:id="@+id/send_information"    android:layout_marginTop="50dp"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:text="send"    android:layout_marginRight="110dp"    />   <TextView    android:id="@+id/receive_information"    android:layout_marginTop="50dp"    android:text="receive"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    />  </LinearLayout> </LinearLayout> 

Java 源码:

package com.example.user.anjay; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.TextView; import com.example.user.anjay.R; import org.apache.http.conn.util.InetAddressUtils; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.InetAddress; import java.net.MulticastSocket; import java.net.NetworkInterface; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import java.util.Enumeration; public class MyActivity extends Activity {  private static String LOG_TAG = "WifiMulticastActivity";  Button startBroadCast;  Button stopBroadCast;  TextView send_label;  TextView receive_label;  /* 用于 udpReceiveAndTcpSend 的3个变量 */  Socket socket = null;  MulticastSocket ms = null;  DatagramPacket dp;  @Override  protected void onCreate(Bundle savedInstanceState) {   super.onCreate(savedInstanceState);   setContentView(R.layout.activity_my);   startBroadCast = (Button) findViewById(R.id.start);   stopBroadCast = (Button) findViewById(R.id.stop);   send_label = (TextView) findViewById(R.id.send_information);   receive_label = (TextView) findViewById(R.id.receive_information);   send_label.append("/n/n");   receive_label.append("/n/n");   startBroadCast.setOnClickListener(listener);   stopBroadCast.setOnClickListener(listener);   /* 开一个线程接收tcp 连接*/   new tcpReceive().start();   /* 开一个线程 接收udp多播 并 发送tcp 连接*/   new udpReceiveAndtcpSend().start();  }  private View.OnClickListener listener = new View.OnClickListener() {   @Override   public void onClick(View v) {    if (v == startBroadCast ) {     startBroadCast.setEnabled(false);     stopBroadCast.setEnabled(true);     /* 新开一个线程 发送 udp 多播 */     new udpBroadCast("hi ~!").start();    }    else {     startBroadCast.setEnabled(true);     stopBroadCast.setEnabled(false);    }   }  };  /* 发送udp多播 */  private  class udpBroadCast extends Thread {   MulticastSocket sender = null;   DatagramPacket dj = null;   InetAddress group = null;   byte[] data = new byte[1024];   public udpBroadCast(String dataString) {    data = dataString.getBytes();   }   @Override   public void run() {    try {     sender = new MulticastSocket();     group = InetAddress.getByName("224.0.0.1");     dj = new DatagramPacket(data,data.length,group,6789);     sender.send(dj);     sender.close();    } catch(IOException e) {     e.printStackTrace();    }   }  }  /*接收udp多播 并 发送tcp 连接*/  private class udpReceiveAndtcpSend extends  Thread {   @Override   public void run() {    byte[] data = new byte[1024];    try {     InetAddress groupAddress = InetAddress.getByName("224.0.0.1");     ms = new MulticastSocket(6789);     ms.joinGroup(groupAddress);    } catch (Exception e) {     e.printStackTrace();    }    while (true) {     try {      dp = new DatagramPacket(data, data.length);      if (ms != null)         ms.receive(dp);     } catch (Exception e) {      e.printStackTrace();     }     if (dp.getAddress() != null) {      final String quest_ip = dp.getAddress().toString();      /* 若udp包的ip地址 是 本机的ip地址的话,丢掉这个包(不处理)*/      //String host_ip = getLocalIPAddress();      String host_ip = getLocalHostIp();      System.out.println("host_ip:  --------------------  " + host_ip);      System.out.println("quest_ip: --------------------  " + quest_ip.substring(1));      if( (!host_ip.equals(""))  && host_ip.equals(quest_ip.substring(1)) ) {       continue;      }      final String codeString = new String(data, 0, dp.getLength());      receive_label.post(new Runnable() {       @Override       public void run() {        receive_label.append("收到来自: /n" + quest_ip.substring(1) + "/n" +"的udp请求/n");        receive_label.append("请求内容: " + codeString + "/n/n");       }      });      try {       final String target_ip = dp.getAddress().toString().substring(1);       send_label.post(new Runnable() {        @Override        public void run() {         send_label.append("发送tcp请求到: /n" + target_ip + "/n");        }       });       socket = new Socket(target_ip, 8080);      } catch (IOException e) {       e.printStackTrace();      } finally {       try {        if (socket != null)         socket.close();       } catch (IOException e) {        e.printStackTrace();       }      }     }    }   }  }  /* 接收tcp连接 */  private class tcpReceive extends  Thread {   ServerSocket serverSocket;   Socket socket;   BufferedReader in;   String source_address;   @Override   public void run() {    while(true) {     serverSocket = null;     socket = null;     in = null;     try {      Log.i("Tcp Receive"," new ServerSocket ++++++++++");      serverSocket = new ServerSocket(8080);      socket = serverSocket.accept();      Log.i("Tcp Receive"," get socket ++++++++++++++++");      if(socket != null) {       in = new BufferedReader(new InputStreamReader(socket.getInputStream()));       StringBuilder sb = new StringBuilder();       sb.append(socket.getInetAddress().getHostAddress());       String line = null;       while ((line = in.readLine()) != null ) {        sb.append(line);       }       source_address = sb.toString().trim();       receive_label.post(new Runnable() {        @Override        public void run() {         receive_label.append("收到来自: "+"/n" +source_address+"/n"+"的tcp请求/n/n");        }       });      }     } catch (IOException e1) {      e1.printStackTrace();     } finally {      try {       if (in != null)        in.close();       if (socket != null)        socket.close();       if (serverSocket != null)        serverSocket.close();      } catch (IOException e) {       e.printStackTrace();      }     }    }   }  }  public String getLocalHostIp() {   String ipaddress = "";   try {    Enumeration<NetworkInterface> en = NetworkInterface      .getNetworkInterfaces();    // 遍历所用的网络接口    while (en.hasMoreElements()) {     NetworkInterface nif = en.nextElement();// 得到每一个网络接口绑定的所有ip     Enumeration<InetAddress> inet = nif.getInetAddresses();     // 遍历每一个接口绑定的所有ip     while (inet.hasMoreElements()) {      InetAddress ip = inet.nextElement();      if (!ip.isLoopbackAddress()        && InetAddressUtils.isIPv4Address(ip        .getHostAddress())) {       return ip.getHostAddress();      }     }    }   }   catch(SocketException e)   {     Log.e("feige", "获取本地ip地址失败");     e.printStackTrace();   }   return ipaddress;  }  private String getLocalIPAddress() {   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();      if (!inetAddress.isLoopbackAddress()) {       return inetAddress.getHostAddress().toString();      }     }    }   } catch (SocketException ex) {    Log.e(LOG_TAG, ex.toString());   }   return null;  }  // 按下返回键时,关闭 多播socket ms  @Override  public void onBackPressed() {   ms.close();   super.onBackPressed();  }  @Override  public boolean onCreateOptionsMenu(Menu menu) {   // Inflate the menu; this adds items to the action bar if it is present.   getMenuInflater().inflate(R.menu.my, menu);   return true;  }  @Override  public boolean onOptionsItemSelected(MenuItem item) {   // Handle action bar item clicks here. The action bar will   // automatically handle clicks on the Home/Up button, so long   // as you specify a parent activity in AndroidManifest.xml.   int id = item.getItemId();   if (id == R.id.action_settings) {    return true;   }   return super.onOptionsItemSelected(item);  } } 

如果有错漏的地方,还请批评指正。毕竟是初学者,不出错,不疏忽是不可能的。

正文到此结束
Loading...