我正在使用UDP在Android上编写一个简单的聊天应用程序。我有一个用于接收数据包的线程(内部类)。 fSocket侦听端口11200以获取数据包。
private class fThread extends Thread {
private int LISTENING_PORT = 11200;
DatagramSocket fSocket;
DatagramPacket fpacket;
public fThread() {
try {
fSocket= new DatagramSocket(LISTENING_PORT);
fSocket.setBroadcast(false);
}catch (IOException e) {}
}
public void run() {
try {
while (true) {
byte[] buf = new byte[1024];
fpacket = new DatagramPacket(buf, buf.length);
fSocket.receive(fpacket);
//some other code below
}
}
}
private void Write(byte[] newfpacket,String DestIP1) {
try {
String data = new String (newfpacket);
DatagramPacket toForward = new DatagramPacket(data.getBytes(),data.length(),InetAddress.getByName(DestIP1.trim()), LISTENING_PORT);
uniSocket.setBroadcast(false);
uniSocket.send(toForward);
catch (UnknownHostException e1) {
android.util.Log.i(TAG1,"Unknown host exception:"+e1.getMessage());
e1.printStackTrace();
} catch (IOException e) {
android.util.Log.i(TAG1,"Some IO exception: "+e.getMessage());
e.printStackTrace();
}
当我点击一个按钮时,我打电话给 fThread fthread = new fThread(); fthread.Write(somemessage," 192.168.1.105"),我得到一个我知道的networkonmainthread异常 这是因为写入是在主线程上完成的,并且必须是它自己的线程或AsyncTAsk。 基本上我想在按下按钮时发送UDP数据包,在某些destIP上发送LISTENING_PORT。我尝试这样做,但不知道如何进一步使线程发送单个数据包,每当我点击一个按钮。
private class sendThread extends Thread { //for sending packet to listening port
DatagramSocket uniSocket;
void run (){
}
}
答案 0 :(得分:0)
您可以做的一件事是使用ConcurrentLinkedQueue<Object>
。在Thread
或AsynTask
中,您需要检查该队列是否有要发送的内容,在这种情况下,您将从队列中删除它(轮询)并发送它。在单击按钮的主线程中,您只需创建对象并将其放入队列queue.add()
,这样您就不会收到异常。 object
只是一个保存要发送的数据(字节)的类,还有数据,您可以保留目标IP地址,端口号等。请参阅ConcurrentLinkedQueue
手册对于add
和poll
对象的方法。我有工作的例子,如果你需要它,是为TCP,虽然这个想法适用于你的情况。
您需要在启动时启动AyncTask或Thread,例如,当队列为空时,此线程或asyntask会休眠Thread.sleep(250)
。当你有什么要从队列发送poll
并发送它。
编辑(exmaples):
// this is the class used to send the packets (data)
public class QueueItem
{
private static final String defaultIP = "192.168.1.150";
private static final short defaultPort = 3030;
public byte[] data = null;
public String dstIP;
public short dstPort;
public QueueItem(byte[] theData) {
this(theData, "", 0);
}
public QueueItem(byte[] theData, String theIP) {
this(theData, theIP, 0);
}
public QueueItem(byte[] theData, String theIP, int thePort) {
this.data = null;
if (theData != null && theData.length > 0)
{
data = new byte[theData.length];
for (int i = 0; i < theData.length; i++)
this.data[i] = theData[i];
}
if (theIP.trim().length() > 0) this.dstIP = theIP.trim();
else this.dstIP = defaultIP; // for example
if (thePort != 0) this.dstPort = (short) thePort;
else this.dstPort = defaultPort; // for example
}
}
// To declare the Queue
public static final ConcurrentLinkedQueue<QueueItem> myQueue = new ConcurrentLinkedQueue<QueueItem>();
public static boolean Terminated=false;
// To queue something do like this:
QueueItem qItem = new QueueItem("This is a test message".getBytes());
myQueue.add(qItem);
// in the doInBackground of your AsyncTask
while (!Terminated)
{
while (!Terminated && myQueue.isEmpty())
{
Thread.sleep(250);
}
if (Terminated) break;
QueueItem qItem = myQueue.poll();
if (qItem != null)
{
DatagramPacket toForward = new DatagramPacket(qItem.data, qItem.data.length,InetAddress.getByName(qItem.dstIP, qItem.dstPort));
uniSocket.setBroadcast(false);
uniSocket.send(toForward);
}
}