gpt4 book ai didi

android - Android 中 UDP 多播中的丢包

转载 作者:行者123 更新时间:2023-11-29 01:22:19 26 4
gpt4 key购买 nike

我创建了一个应用程序,它提供了 android 中 UDP 数据包丢失的统计信息。这是我的应用程序架构。1)多播UDP数据包的应用程序。下面是它的代码:

package rockwell.multicastserverproj;

import android.content.Context;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;

public class MainActivity extends AppCompatActivity {

EditText txtMsg;
EditText txtPackets;
EditText txtMs;
EditText txtBytes;
EditText txtCount;
byte[] rtpData;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();

}
});

/*Thread thrClient = new Thread(new ReceiveMulticast());
thrClient.start();*/

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, 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();

//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}

return super.onOptionsItemSelected(item);
}

public void onBtnClicked(View view)
{
Thread threadTotalPackets = new Thread(new SendMulticast());
threadTotalPackets.start();

Thread thread = new Thread(new MulticastPackets());
thread.start();
//Toast.makeText(this,"Message multicasted",Toast.LENGTH_LONG).show();


}

public class MulticastPackets implements Runnable{

@Override
public void run() {
InetAddress group = null;
MulticastSocket multiSocket = null;
int PORT = 6500;
txtPackets =(EditText)findViewById(R.id.txtPackets);
txtMs = (EditText)findViewById(R.id.txtMs);
txtBytes = (EditText)findViewById(R.id.txtBytes);
txtCount = (EditText)findViewById(R.id.txtCount);

int noOfPackets = Integer.parseInt(txtPackets.getText().toString());
int delayMS = Integer.parseInt(txtMs.getText().toString());
int packetSize = Integer.parseInt(txtBytes.getText().toString());
int cntPacket = Integer.parseInt(txtCount.getText().toString());

WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiManager.MulticastLock mLock = wifi.createMulticastLock("mylock");
mLock.acquire();

try{
group = InetAddress.getByName("230.0.0.1");
multiSocket = new MulticastSocket(PORT);
} catch (IOException e) {
e.printStackTrace();
}

for(int pcktCnt=1; pcktCnt<=noOfPackets; pcktCnt++) {

rtpData = new byte[packetSize];
int cnt = unsigned_int(pcktCnt);
byte[] seqArr = null;
seqArr = toBytes(cnt);
byte varFirst = 0xa;
byte varSecond = 0x5;

for(int i=4;i<packetSize;i+=2)
{
if(i%4 ==0) {
rtpData[i] = varFirst;
rtpData[i + 1] = varFirst;
}
else {
rtpData[i] = varSecond;
rtpData[i + 1] = varSecond;
}
}

for(int i=0;i<4;i++)
{
rtpData[i] = seqArr[i];
}

DatagramPacket requestPacket = new DatagramPacket(rtpData, rtpData.length, group, PORT);
try {
for(int i=0;i<cntPacket;i++) {
multiSocket.send(requestPacket);
Thread.sleep(delayMS, 0);
}
int test = fromByteArray(seqArr);
Log.i("Multicast", "Packet send. Sequence number is: " + test);

} catch (Exception e) {
e.printStackTrace();
}
int test = fromByteArray(seqArr);
}

try{

multiSocket.leaveGroup(group);
multiSocket.close();

} catch (IOException e) {
e.printStackTrace();
}
mLock.release();

MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this,"Packet sent",Toast.LENGTH_LONG).show();
}
});
}
}

public class SendMulticast implements Runnable{
@Override
public void run() {
InetAddress group = null;
MulticastSocket multiSocket = null;
int PORT = 5500;
txtPackets =(EditText)findViewById(R.id.txtPackets);
txtBytes = (EditText)findViewById(R.id.txtBytes);

String requestString = txtPackets.getText().toString();
String strPackSize = txtBytes.getText().toString();

requestString = requestString +";" + strPackSize;
Log.i("reqstring",requestString);
byte[] requestData = new byte[requestString.length()];
requestData = requestString.getBytes();

WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiManager.MulticastLock mLock = wifi.createMulticastLock("mylock");
mLock.acquire();

try{
group = InetAddress.getByName("230.0.0.1");
multiSocket = new MulticastSocket(PORT);
multiSocket.joinGroup(group);
} catch (IOException e) {
e.printStackTrace();
}

try{
DatagramPacket requestPacket = new DatagramPacket(requestData, requestData.length, group, PORT);
multiSocket.send(requestPacket);
Log.i("multicastproj","message multicasted");

} catch (IOException e) {
e.printStackTrace();
}
try{
multiSocket.leaveGroup(group);
multiSocket.close();

} catch (IOException e) {
e.printStackTrace();
}
mLock.release();
}
}

static int unsigned_int(int nb) {
if (nb >= 0)
return (nb);
else
return (256 + nb);
}

public byte[] toBytes(int i)
{
byte[] result = new byte[4];

result[0] = (byte) (i >> 24);
result[1] = (byte) (i >> 16);
result[2] = (byte) (i >> 8);
result[3] = (byte) (i /*>> 0*/);

return result;
}

public int fromByteArray(byte[] bytes) {
return bytes[0] << 24 | (bytes[1] & 0xFF) << 16 | (bytes[2] & 0xFF) << 8 | (bytes[3] & 0xFF);
}



public class ReceiveMulticast implements Runnable{
@Override
public void run() {
byte[] requestData = new byte[1024];
InetAddress group = null;
MulticastSocket multiSocket = null;
int PORT = 4500;

WifiManager wifi = (WifiManager) getSystemService(getApplicationContext().WIFI_SERVICE);
WifiManager.MulticastLock mLock = wifi.createMulticastLock("mylock");
mLock.acquire();

try{
group = InetAddress.getByName("230.0.0.1");
multiSocket = new MulticastSocket(PORT);
multiSocket.joinGroup(group);
} catch (IOException e) {
e.printStackTrace();
}

try{
while(true)
{
DatagramPacket requestPacket = new DatagramPacket(requestData, requestData.length);
multiSocket.receive(requestPacket);

String requestString = new String(requestPacket.getData(), 0, requestPacket.getLength());
Log.d("CreateMulticastServer", "Got request = " + requestString);

/*txtMsg = (EditText)findViewById(R.id.txtMsg);
txtMsg.setText(requestString);*/
}

} catch (IOException e) {
e.printStackTrace();
}

try{
multiSocket.leaveGroup(group);
multiSocket.close();

} catch (IOException e) {
e.printStackTrace();
}

mLock.release();

}
}
}

接收这些组播 UDP 数据包的另一个应用程序

持续运行并接收组播数据包的服务:

package rockwell.packetstatistics;

import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.WifiManager;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;

/**
* Created by mmjoshi on 2/10/2016.
*/
public class PacketReceive_Service extends IntentService {
boolean flag = true;
int packetSize = 0;
public PacketReceive_Service() {
super("PacketReceive_Service");
}

@Override
protected void onHandleIntent(Intent intent) {
String strVar = intent.getStringExtra("vari");
Log.i("onstartservice","string is " + strVar);

Thread thread = new Thread(new PacketThread());
thread.setPriority(Thread.MAX_PRIORITY);
thread.start();

Thread thread1 = new Thread(new TotalPackets());
thread1.start();
}

public class PacketThread implements Runnable
{
@Override
public void run() {
InetAddress group = null;
MulticastSocket multiSocket = null;
WifiManager.MulticastLock mLock = null;
int prevSeqNo=0;
String strMissingPackets="";
int TotalpacketsReceived = 0;
try {

if(packetSize == 0)
packetSize = 1036;

byte[] requestData = new byte[packetSize];
int PORT = 6500;
byte varFirst = 0xa;
byte varSecond = 0x5;

WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
mLock = wifi.createMulticastLock("mylock");
mLock.setReferenceCounted(true);
mLock.acquire();

try{
group = InetAddress.getByName("230.0.0.1");
multiSocket = new MulticastSocket(PORT);
multiSocket.joinGroup(group);
} catch (IOException e) {
e.printStackTrace();
}

while (flag) {
final DatagramPacket requestPacket = new DatagramPacket(requestData, requestData.length);
multiSocket.receive(requestPacket);

byte[] resultData = requestPacket.getData();

byte[] seqArr = new byte[4];
for(int i=0;i<4;i++){
seqArr[i] = resultData[i];
}

int seqNo = fromByteArray(seqArr);
Log.i("RecvPackets","multiple packet received # is: " + seqNo);
if(prevSeqNo!=seqNo)
{
TotalpacketsReceived++;
if(prevSeqNo!=0)
{
if((seqNo - prevSeqNo)>1)
{
for(int k=(prevSeqNo+1);k<seqNo;k++)
{
strMissingPackets += k + ", ";
sendResultMessage("Missing;" + String.valueOf(k));
Log.i("RecvPackets","Packet missing. Missing# is: " + k);
}
}
}
for(int i=4;i<packetSize;i+=2)
{
if(i%4 ==0) {
if(resultData[i] != varFirst || resultData[i+1] != varFirst)
{
if(seqNo != 1) {
sendResultMessage("DataError;" + String.valueOf(seqNo));
Log.i("DataCheck", "Error in data");
}
}
}
else {
if(resultData[i] != varSecond || resultData[i+1] != varSecond)
{
if(seqNo != 1) {
sendResultMessage("DataError;" + String.valueOf(seqNo));
Log.i("DataCheck", "Error in data");
}
}
}
}
prevSeqNo = seqNo;
Log.i("MulticastService", "Packet size is: " + packetSize + " Packet receive. Sequence number is: " + seqNo);
sendResultMessage("TotalPacketsReceived;" + String.valueOf(TotalpacketsReceived));
}
}


} catch (IOException e) {
Log.i("DEU Service", "In cache");
flag = false;
e.printStackTrace();
}
finally {
try {
if(multiSocket != null) {
if(group != null)
multiSocket.leaveGroup(group);
multiSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}

if(mLock != null)
mLock.release();
}
}
}

private void sendResultMessage(String strPacks) {
Intent intent = new Intent("intData");
intent.putExtra("result",strPacks);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
private void sendTotalPackets(String strPacks) {
Intent intent = new Intent("intPacket");
intent.putExtra("result",strPacks);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
public int fromByteArray(byte[] bytes) {
return bytes[0] << 24 | (bytes[1] & 0xFF) << 16 | (bytes[2] & 0xFF) << 8 | (bytes[3] & 0xFF);
}

public class TotalPackets implements Runnable{
@Override
public void run() {
byte[] requestData = new byte[1024];
InetAddress group = null;
MulticastSocket multiSocket = null;
int PORT = 5500;

WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiManager.MulticastLock mLock = wifi.createMulticastLock("mylock");
mLock.acquire();

try{
group = InetAddress.getByName("230.0.0.1");
multiSocket = new MulticastSocket(PORT);
multiSocket.joinGroup(group);
} catch (IOException e) {
e.printStackTrace();
}

try{
while(true)
{
DatagramPacket requestPacket = new DatagramPacket(requestData, requestData.length);
multiSocket.receive(requestPacket);

String requestString = new String(requestPacket.getData(), 0, requestPacket.getLength());
Log.i("requestString",requestString);
String[] spltStr = requestString.split(";");
packetSize = Integer.parseInt(spltStr[1].toString());
Log.i("service","Packet size is: " + spltStr[1].toString() + " Total Packs: " + spltStr[0]);
sendTotalPackets(spltStr[0].toString());
/*txtMsg = (EditText)findViewById(R.id.txtMsg);
txtMsg.setText(requestString);*/
}

} catch (IOException e) {
e.printStackTrace();
}

try{
multiSocket.leaveGroup(group);
multiSocket.close();

} catch (IOException e) {
e.printStackTrace();
}

mLock.release();
}
}
}

所以,我的问题是,在服务端,当我收到数据包时,大部分数据包丢失了 5-7%。这意味着,如果我以 5 毫秒的间隔发送 1000 个 512 字节的数据包,接收端将丢失 50-70 个数据包。

有什么方法可以减少丢包吗?或者我的代码是否有任何改进的机会,以便减少丢包?

提前致谢。

最佳答案

您无能为力。

  1. UDP 是一个传输层,没有交付保证。

  2. wifi 上的数据包丢失会因接入点的不同品牌/型号/配置及其运行的设备而异。

    例如,5ghz 可能表现更好,因为空气波通常更干净,但它不像 2.4 ghz 那样穿透墙壁。

并非所有 Android 设备都使用相同的 wifi radio 。

如果您使用在 MAC 层进行多播到单播转换的接入点,您实际上可以获得几乎 0% 的数据包丢失。所以你在你的应用软件中使用UDP。然后接入点在 802.11 层内部进行重传。例如,Cisco 和 Xirrus 具有多播到单播的转换选项,并且产生几乎 0% 的数据包丢失。然而,这是要付出代价的,因为它不能很好地扩展,因为每个多播流都是单独发送到每个订阅的设备。

嗯...你能用软件做什么....

“处理”组播丢包的方法:

前向纠错。

  • 您可以将每个数据包发送两次。 AABBCCDDEE
  • 您可以发送每个数据包两次但会延迟:ABACBDCED
  • 部分数据可以发送两次:AABCCDE任何前向纠错方案都会增加带宽并增加延迟。

损失隐瞒

  • 您可以尝试估算损失之间的数据。

您还没有真正陈述您的申请,因此很难就处理损失提出建议。由于您的 5 毫秒限制,听起来您正在传输 48khz 音频的 240 帧数据包。

关于android - Android 中 UDP 多播中的丢包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36071979/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com