Android手机发送和监听UDP数据

UDP协议中文名是用户数据报协议,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。在OSI模型中,在第四层——传输层,处于IP协议的上一层。与所熟知的TCP(传输控制协议)协议一样,UDP协议直接位于IP(网际协议)协议的顶层。根据OSI(开放系统互连)参考模型,UDP和TCP都属于传输层协议。UDP协议的主要作用是将网络数据流量压缩成数据包的形式。一个典型的数据包就是一个二进制数据的传输单位。每一个数据包的前8个字节用来包含报头信息,剩余字节则用来包含具体的传输数据。UDP数据包是面向无连接的,用户发出数据包不需要得到确认,因此是是不可靠的传输。

Android的UDP的数据传输和JAVA里没有什么区别。

UDP工具类:

package com.wifi.udp;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;


/**
 * UDP工具类
 * @author Sunward
 *
 */
public class UDPUtils implements Runnable {


public boolean keepRunning = true;//线程开始标志
public static final String TAG = "TEST";
//发送目的主机IP和端口
    private static String SERVER_IP;
    private static int SERVER_PORT;
    
    //本机监听的端口
    private static int LOCAL_PORT = 8929;
    
    //发送的消息
    private String message = "test";
    
    //服务器接收的消息
    private String receive;
    
    //Handler传递的数据
    private Message msg;
    //Message传递的Buddle参数
    private Bundle bundle;
    
    //wifi名和密码
    private String SSID,password;


    public UDPUtils(){

}


public UDPUtils(String Server_IP, int Server_Port) {
SERVER_IP = Server_IP;
SERVER_PORT = Server_Port;
}


public void setMessage(String message) {
this.message = message;
}
public String getMessage() {
return message;
}




/**
* 线程停止标志
* @param keepRunning
*/
public void setKeepRunning(boolean keepRunning) {
this.keepRunning = keepRunning;
}

public boolean getKeepRunning(){
return this.keepRunning;
}

 
/**
* 服务端监听程序
*/
public void StartListen()  {
keepRunning = getKeepRunning();
DatagramSocket socket = null;  
        byte[] data = new byte[1024];  
        DatagramPacket packet = new DatagramPacket(data, data.length);  
          
        try {  
            socket = new DatagramSocket(LOCAL_PORT);  
            socket.setBroadcast(true);
            Log.i(TAG, "socket");  
//          socket.setSoTimeout(200);  
        } catch(Exception e) {  
            e.printStackTrace();  
            return;  
        }  
          
        while (keepRunning) {              
            try {  
                //等待客户机连接  
                packet.setData(data);  
                Log.e(TAG, "receive0"); 
                socket.receive(packet);  
                receive = new String(packet.getData(), 0, packet.getLength());  
                
                msg = new Message();
                bundle = new Bundle();
                
                //把数据放到buddle中
                bundle.putString("receive", receive);
                //把buddle传递到message
                msg.setData(bundle);
                myHandler.sendMessage(msg);
                
            } catch (Exception e) {  
                continue;  
            }  
        }  
          
        if (socket != null) {  
            socket.close();  
            socket = null;  
        }  
}
//利用Handler将接收的数据实时打印出来
Handler myHandler = new Handler(){
@Override
public void handleMessage(Message msg)
{
super.handleMessage(msg);
Bundle bundle=new Bundle();
//从传过来的message数据中取出传过来的绑定数据的bundle对象
bundle = msg.getData();
receive = bundle.getString("receive");
setMessage(receive);
}
};

public void sendControInfo(String message){

try {  
            DatagramSocket sendSocket = new DatagramSocket();  
           
            byte[] configInfo = message.getBytes();
           
            InetAddress ip = InetAddress.getByName(SERVER_IP);  //即目的IP
            DatagramPacket sendPacket = new DatagramPacket(configInfo, configInfo.length, ip ,SERVER_PORT);// 创建发送类型的数据报:  
  
            sendSocket.send(sendPacket);    // 通过套接字发送数据:             
              
            sendSocket.close();  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
}

@Override
public void run() {
StartListen();
}
}




MainActivity

package com.wifi.main;


import java.lang.Thread.State;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.regex.Pattern;


import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;


import com.example.jushi_blub.R;
import com.wifi.udp.UDPUtils;
import com.wifi.utils.MyApplication;




public class MainActivity extends Activity implements OnClickListener{
public static final String TAG = "MainActivity";  
    private Button send_udp,receive_udp,coapServer,coapClient;
    private long exitTime = 0;
    
    //发送或者接收的文本
    public static EditText send_msg,receive_msg;
    //目的主机IP
    private String SERVER_IP;
    private int SERVER_PORT;
    //本机监听端口
    private int LOCAL_PORT;
    
    private TextView infomation;
    
    private UDPUtils udpUtils;
    private String message;
    
    private Thread thread;
    
    private Map<String, Object> map;
    //用户输入的灯泡ID
    private int  bulbID;
    
    //用来存储全局变量,用于Activity之间的传递
    private MyApplication myApplication;
    //定时器,用来检测是否接收到成功消息
    private Timer timer;
    
    //灯泡的状态
    private String status = "off";
    
    /**
     * 初始化
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        initViews();
        myApplication = (MyApplication)this.getApplicationContext();
        map = myApplication.getMap();
        
        if (!map.isEmpty()) {
        SERVER_IP = map.get("IP").toString();
        SERVER_PORT = Integer.parseInt(map.get("Port").toString().trim());
        LOCAL_PORT = Integer.parseInt(map.get("LOCAL_PORT").toString().trim());
}else {

SERVER_IP = "192.168.0.107";
        SERVER_PORT = 9090;
        LOCAL_PORT = 8929;
}
        udpUtils = new UDPUtils(SERVER_IP,SERVER_PORT, LOCAL_PORT);
        infomation.append("目的IP: "+SERVER_IP+"\n"+"目的端口: "+SERVER_PORT+"\n");
        infomation.append("本地端口: " +LOCAL_PORT);
        
    }

    
    /**
     * 控件初始化
     */
    public void initViews(){
        send_udp = (Button) findViewById(R.id.send_udp);
        send_msg = (EditText) findViewById(R.id.message);
        receive_msg = (EditText) findViewById(R.id.receive);
        infomation =(TextView) findViewById(R.id.information);


        send_udp.setOnClickListener(MainActivity.this);
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }


    /**  
     * 监听Back键按下事件,方法1:  
     * 注意:  
     * super.onBackPressed()会自动调用finish()方法,关闭  
     * 当前Activity.  
     */    
   /* @Override    
    public void onBackPressed() {    
        super.onBackPressed();    
    }    */
    
    
    @Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO 按两次返回键退出应用程序
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
// 判断间隔时间 大于2秒就退出应用
if ((System.currentTimeMillis() - exitTime) > 2000) {
// 应用名
String applicationName = getResources().getString(
R.string.app_name);
String msg = "再按一次返回键退出";
//String msg1 = "再按一次返回键回到桌面";
Toast.makeText(MainActivity.this, msg, 0).show();
// 计算两次返回键按下的时间差
exitTime = System.currentTimeMillis();
} else {
// 关闭应用程序
finish();
// 返回桌面操作
// Intent home = new Intent(Intent.ACTION_MAIN);
// home.addCategory(Intent.CATEGORY_HOME);
// startActivity(home);
}
return true;
}
return super.onKeyDown(keyCode, event);
}
    /**
     * 菜单单击事件
     */
    @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.wifi_config) {
        Intent intent = new Intent();
        intent.setClass(MainActivity.this, WIFIActivity.class);
        this.startActivity(intent);
            return true;
        }
        if (id == R.id.ip_config) {
        Intent intent = new Intent();
        intent.setClass(MainActivity.this, IPActivity.class);
        this.startActivity(intent);
            return true;
}
        return super.onOptionsItemSelected(item);
    }






    @Override
public void onClick(View view) {


switch (view.getId()) {  
        case R.id.send_udp:
       
                new Thread(){
                @Override
public void run(){
                udpUtils.sendControInfo("Hello");
                }
                }.start();

thread = new Thread(udpUtils);

thread.start();

       break;

        default:  
            break;  
        }  
}
    
    /**
     * 判断输入的是否为数字
     * @param str
     * @return
     */
    public static boolean isInteger(String str) {  
        Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");  
        return pattern.matcher(str).matches();  
  }

 

/**
* 判断开灯返回的数据
* @param receive
* @return
*/


@Override
    protected void onDestroy() {  
    super.onDestroy();
    //关闭线程
        udpUtils.setKeepRunning(false); 
    }  

}


效果图:



在同一个局域网下进行测试,目的主机是电脑IP地址是192.168.0.107,安装了TCP/UDPb捕获软件,手机发送开关信号电脑的软件能够接收到,并且电脑发送消息手机也能监听到。这里要注意:

1.手机的点击按钮事件中的发送数据一定要放在线程里运行,否则会报主线程不能处理网络请求的相关异常。

2.监听接收数据时,也要启动一个线程,在UDPUtils中监听数据的端口号不能和发送的端口号相同,且接收数据需要放到Handler中处理,否则不能实时将数据打印在手机上。


  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android 提供了一种监听数据上下行的机制,可以帮助我们实时监测网络请求的发送接收。下面我将简单介绍一下如何实现这个功能。 首先,我们可以使用 Android 提供的网络请求库(例如OkHttp、Retrofit等)来发送接收数据。这些库提供了相应的回调接口,可以监听网络请求的状态和数据。 对于发送数据,我们可以使用库中的回调接口中的 `onRequestSent()` 方法来获取发送数据。例如,我们可以将请求体转换成字符串形式,然后在请求发送之前调用 `onRequestSent()` 方法来记录发送数据。如下所示: ``` RequestBody requestBody = request.body(); BufferedSink buffer = new Buffer(); requestBody.writeTo(buffer); String requestData = buffer.readUtf8(); // 在请求发送之前记录发送数据 onRequestSent(requestData); ``` 对于接收数据,我们可以使用回调接口中的 `onResponseReceived()` 方法来获取接收到的数据。例如,我们可以将返回的响应体转换成字符串形式,然后在接收到响应之后调用 `onResponseReceived()` 方法来记录接收到的数据。如下所示: ``` ResponseBody responseBody = response.body(); String responseData = responseBody.string(); // 在接收到响应之后记录接收到的数据 onResponseReceived(responseData); ``` 然后,我们可以在 `onRequestSent()` 和 `onResponseReceived()` 方法中添加自己的逻辑,例如将数据存储到数据库中或者显示在界面上。 需要注意的是,在监听数据上下行时,要适当处理异常情况,例如网络连接错误或者请求被取消的情况,以确保数据的准确性和完整性。 总而言之,通过使用网络请求库提供的回调接口,我们可以方便地监听Android应用程序的数据上下行,从而实现对网络请求的实时监测和处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值