DatagramSocket.receive只接收前两个Datagrams

时间:2013-02-19 19:08:34

标签: android udp

我通过UDP向android应用程序发送一些数据。因此我创建了以下UDPReceiver-Class:

package com.example.urowatch;

import java.net.*;
import java.nio.ByteBuffer;
import java.io.*;

public class UDPReceiver extends Thread
{
private DatagramSocket m_Socket;
private int m_BufferSize;
private Boolean m_End = false;

private int m_TotalLength;
private int m_Received;
private byte[] m_Buffer;

private byte[] m_Result;
private Boolean m_IsNewResult = false;

private float m_Progress;

private int m_ImageCount = 0;
private int m_FrameErrors = 0;

public UDPReceiver(String name, int port, int bufferSize) throws IOException
{
    super(name);

    m_Socket = new DatagramSocket(port);
    m_BufferSize = bufferSize;
    m_Socket.setBroadcast(true);
    m_Socket.setReceiveBufferSize(m_BufferSize);
}

public void run()
{
    while(!m_End)
    {
        try
        {
            byte[] buf = new byte[m_BufferSize];
            DatagramPacket packet = new DatagramPacket(buf, buf.length);
            m_Socket.receive(packet);
            ProcessData(packet);
        }
        catch (IOException e)
        {
            if (!m_Socket.isClosed())
                e.printStackTrace();
        }
    }
}

private void ProcessData(DatagramPacket packet)
{
    if (packet.getLength() == 4)
    {
        ByteBuffer bb = ByteBuffer.wrap(packet.getData());
        m_TotalLength = bb.getInt();
        if (m_Received != 0)
            m_FrameErrors++;
        m_Received = 0;
        m_Buffer = new byte[m_TotalLength];
    }
    else if (m_Buffer != null && m_Received != m_TotalLength)
    {
        int length = packet.getLength();
        System.arraycopy(packet.getData(), 0, m_Buffer, m_Received, length);
        m_Received += length;
        m_Progress = 100 * (float)m_Received/(float)m_TotalLength;

        if (m_Received == m_TotalLength)
        {
            m_Result = new byte[m_TotalLength];
            System.arraycopy(m_Buffer, 0, m_Result, 0, m_TotalLength);
            m_IsNewResult = true;
            m_ImageCount++;
            m_Received = 0;
        }
    }
}

public Boolean IsNewResult()
{
    return m_IsNewResult;
}
public byte[] GetResult()
{
    m_IsNewResult = false;
    return m_Result;
}
public float GetProgress()
{
    return m_Progress;
}
public float GetRatio()
{
    return 100 * (float)m_ImageCount / (float)m_FrameErrors;
}

public void stopServer()
{
    m_End = true;
    if (m_Socket != null)
        m_Socket.close();
}
}

我正在使用这个类:

package com.example.urowatch;

import java.io.IOException;
import java.text.DecimalFormat;

import android.os.*;
import android.app.Activity;
import android.app.AlertDialog;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import android.support.v4.app.NavUtils;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.os.Build;

public class LiveActivity extends Activity {
private static ImageView m_ImageView1;
private static TextView m_TextView1;
private static DecimalFormat m_DF;
private static Context m_Context;
private UDPReceiver m_Receiver;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_live);
    // Show the Up button in the action bar.
    setupActionBar();

    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);

    m_ImageView1 = (ImageView)findViewById(R.id.imageView1);
    m_TextView1 = (TextView)findViewById(R.id.textView1);
    m_Context = this;

    m_DF = new DecimalFormat("00.00");
}

/**
 * Set up the {@link android.app.ActionBar}, if the API is available.
 */
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void setupActionBar() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        getActionBar().setDisplayHomeAsUpEnabled(true);
    }
}

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

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case android.R.id.home:
        // This ID represents the Home or Up button. In the case of this
        // activity, the Up button is shown. Use NavUtils to allow users
        // to navigate up one level in the application structure. For
        // more details, see the Navigation pattern on Android Design:
        //
        // http://developer.android.com/design/patterns/navigation.html#up-vs-back
        //
        NavUtils.navigateUpFromSameTask(this);
        return true;
    }
    return super.onOptionsItemSelected(item);
}

private static Handler MyHandler = new Handler()
{
    @Override
    public void handleMessage(Message msg)
    {
        if (msg.what == 100)
        {
            float[] infos = (float[])msg.obj;
            m_TextView1.setText("Empfange Bild: " + m_DF.format(infos[0]) + "% (FrameErrors: " + m_DF.format(infos[1]) + "%)");
        }
        else if (msg.what == 101)
        {
            byte[] b = (byte[])msg.obj;
            m_TextView1.setText("Empfange Bild: 100,00%");
            m_ImageView1.setImageBitmap(BitmapFactory.decodeByteArray(b, 0, b.length));
        }
        else if (msg.what == 102)
        {
            AlertDialog.Builder b = new AlertDialog.Builder(m_Context);
            b.setTitle("Fehler");
            b.setMessage("Es ist folgende Exception aufgetreten:\n" + (Exception)msg.obj);
            b.setNeutralButton("OK", null);
            b.show();
        }
    }
};

@Override
public void onBackPressed() {
    super.onBackPressed();
    if (m_Receiver != null)
        m_Receiver.stopServer();
    finish();
}

@Override
public void onPause()
{
    m_Receiver.stopServer();
    super.onPause();
}

@Override
protected void onResume()
{
    try {
        m_Receiver = new UDPReceiver("UDPReceiver", 5678, 1024);
        m_Receiver.start();
    } catch (IOException e1)
    {
        // TODO Auto-generated catch block
        e1.printStackTrace();

        AlertDialog.Builder b = new AlertDialog.Builder(this);
        b.setTitle("Fehler");
        b.setMessage("Es ist folgende Exception aufgetreten:\n" + e1);
        b.setNeutralButton("OK", null);
        b.show();
    }

//      Thread thread = new Thread()
//      {
//          @Override
//          public void run()
//          {
//              while(true)
//              {
//                  try {
                    //sleep(250);
                    Toast.makeText(getBaseContext(), "Runing Thread", Toast.LENGTH_SHORT).show();
                    Update();


//                  } catch (InterruptedException e) {
//                      // TODO Auto-generated catch block
//                      e.printStackTrace();
//                      MyHandler.sendMessage(MyHandler.obtainMessage(102, e));
//                  }

//              }
//          }
//      };
//      thread.start();
    super.onResume();
}

public void buttonClick(View v)
{
    Update();
}

private void Update()
{
    if (m_Receiver != null)
    {                               
        if (m_Receiver.IsNewResult())
        {
            byte[] b = m_Receiver.GetResult();
            MyHandler.sendMessage(MyHandler.obtainMessage(101, b));
        }
        else
        {
            float[] infos = new float[2];
            infos[0] = m_Receiver.GetProgress();
            infos[1] = m_Receiver.GetRatio();
            MyHandler.sendMessage(MyHandler.obtainMessage(100, infos));
        }
    }
}
}

如您所见,我想通过线程检查UDPReceiver-Object的状态(是否有新的完整字节[]?)。要更新GUI,线程必须向MyHandler发送一条消息,该消息将更新GUI。

此刻我必须单击按钮才能提升buttonClick-Event。后来我想在注释的线程结构中这样做。

现在,这是我的问题: 我开始活动,一切正常。然后我开始用我的UDP-Sender手动发送一个数据包(它可以工作,我用C#-UDP-Receiver验证它)。收到的第一个数据包很好。然后我发送第二个收到的数据包。但是从现在开始,我的断点是m_Socket.receive(数据包);不会再受到打击了!

我不知道这种行为会导致什么,这对我来说非常重要。 如果您有任何想法或猜测,请告诉我。

0 个答案:

没有答案