【问题标题】:Android UDP Communication via local wifiAndroid UDP 通过本地 wifi 通信
【发布时间】:2014-05-07 04:13:04
【问题描述】:

我创建了一个允许通过本地 wifi 发送数据的应用程序。首先,我尝试恢复我的 IP 地址和我所在的域,并且它工作正常(我用 Log.d 验证了它)。

这是ClientThread类:

import java.net.DatagramPacket;
import java.net.InetAddress;

public class ClientThread extends Thread implements Runnable{
    String address;
    String message;
    int port;
    boolean broadcast;
    public ClientThread(String address, String message, int port,boolean broadcast)
    {   super();
        this.address = address;
        this.message = message;
        this.port = port;
        this.broadcast = broadcast;
    }
    public void run() {
        try {   
            DatagramPacket packet1 = new DatagramPacket(message.getBytes()
                    , message.length(), InetAddress.getByName(address), port);
            ChatService.socket.send(packet1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

此外,我创建了这个服务来运行 ServerThread:

公共类 ChatService 扩展服务{

public static DatagramSocket socket;
private ServerThread sThread;
public static String serverIP;
public static final int SERVERPORT = 5555;
private Handler handler = new Handler(); 
private ServerSocket serverSocket;
public static final String BROADCAST_ACTION = "UpdateEvent";
static Intent intent;

@Override
public IBinder onBind(Intent arg0) {
    return null;
}

@Override
public void onCreate() {
    super.onCreate();
    try {
        socket = new DatagramSocket(SERVERPORT);// initialisation du datagramme UDP
        sThread = new ServerThread();
        sThread.start();
    } catch (SocketException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
public class ServerThread extends Thread implements Runnable{

     public void run() {
            try {
                  serverIP = getLocalIpAddress(); 
                  Log.v("addr", serverIP);
                  if (serverIP != null) {
                     serverSocket = new ServerSocket(SERVERPORT);
                     Log.v("socket", "created");
                     while(true) {  //boucle infini                  
                         Socket client = serverSocket.accept();
                         Log.v("client", "received");
                         try {
                            byte[] buf = new byte[1024]; 
                            DatagramPacket packet = new DatagramPacket(buf, buf.length); 
                            ChatService.socket.receive(packet);
                            byte[] result = new byte[packet.getLength()];
                            System.arraycopy(packet.getData(), 0, result, 0, packet.getLength());
                            String msg = new String(result);
                            updateGui(msg, packet.getAddress());
                            ChatService.socket.close();

                         } catch (Exception e) {

                         }
                     }
                  } 
               } catch (Exception e) {}
        }

      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("ServerActivity", ex.toString());
                }
                return null;
       }

        public void updateGui(String msg, InetAddress addr) {

            intent = new Intent(BROADCAST_ACTION);
            intent.putExtra("message", msg);
            intent.putExtra("senderAddr", addr.toString().substring(1, addr.toString().length()));
            if(msg.substring(0, 4).equals("idfu"))
            {
                CollectiveActivity.receiverAddr = addr.toString().substring(1, addr.toString().length());
            }
            sendBroadcast(intent);
        }
}

在我的活动(称为 CollectiveActivity)中,我创建了方法 SendMessage :

 private void sendMessage(String address, String msg, boolean bcast) {
        wifi.ClientThread cThread;
        cThread = new wifi.ClientThread(address, msg, 5555, bcast);
        cThread.start();
    }

当点击“提交”按钮时,我调用了它:

Button submit = (Button) findViewById(R.id.Button); 
             submit.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View arg0) {
                      chatArea.append(Html.fromHtml("<font color='red' style='bold'>"+User.username+": </font>"));
                      chatArea.append(Html.fromHtml("<font color='black'>"+textBox.getText()+"</font> <br/>"));
                      sendMessage("192.168.93.103", "mssg"+User.username+": "+textBox.getText().toString(), true);
                      textBox.setText("");
                }
            })  ;

我没有忘记广播接收器:

 private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.v("msg", "received");
            String message = intent.getStringExtra("message");
            String code = message.substring(0, 4); // message= code(4) + msg 
            String msg = null;
            if(message.length()>4) msg = message.substring(4, message.length());
            if(code.equals("idfr"))
            {
                 if(receiverAddr != null) 
                 {
                    // si qq entre à la chambre de chat
                     addUser(msg, intent.getStringExtra("senderAddr"));
                     Toast toast = Toast.makeText(CollectiveActivity.this, msg+" entered chat room", 1000);
                     toast.show();
                     sendMessage(receiverAddr, "idfu"+DataUser.User.username, false);
                 }
            }
            else if(code.equals("idfu"))
            {
                 addUser(msg, intent.getStringExtra("senderAddr"));
                 Toast toast = Toast.makeText(CollectiveActivity.this, msg+" entered chat room", 1000);
                 toast.show();
                 Log.v("user added with name and address", msg + " " + intent.getStringExtra("senderAddr"));
            }
            else if(code.equals("mssg"))
            {
                 int temp = 0;
                 while(msg.charAt(temp)!=' ') temp++; 
                sender+' '+message1
                 String sender;
                 String message1;
                 sender = msg.substring(0, temp);
                 message1 = msg.substring(temp, msg.length());

                 chatArea.append(Html.fromHtml("<font color='red'>"+sender+" </font>"));
                 chatArea.append(Html.fromHtml("<font color='black'>"+message1+"</font> <br/>"));

                 scrollView.post(new Runnable() {
                    public void run() {
                        scrollView.fullScroll(View.FOCUS_DOWN);
                    }
                 });

            }
        }
    };

最后,这些是我活动的其他方法:

    public void onResume() {
        super.onResume();
        registerReceiver(broadcastReceiver, new IntentFilter(ChatService.BROADCAST_ACTION));
    }  
    public void onPause() {
        super.onPause();
        unregisterReceiver(broadcastReceiver);
    }   
    public void onDestroy() {
        super.onDestroy();
    }

当我运行应用程序时,我无法发送/接收任何消息,并且日志中有两个警告:

java.lang.NullPointerException
at wifi.ClientThread.run(ClientThread.java:31)

我想知道是什么问题,我该如何纠正它。 谢谢

【问题讨论】:

  • 请提供整个堆栈跟踪和public void run() { 行的源行号,以便我们可以将跟踪中的行号与该方法中的行号联系起来。
  • 问题出在 ChatService.socket.send(packet1);

标签: android sockets udp wifi chat


【解决方案1】:

我会注销所有相关值;其中一个没有价值。所以也许:

Log.v(TAG, String.format("message is [%s]; it's size is %d", message, message.length()));                      Log.v(TAG, String.format("address is [%s]; it's size is %d", address, address.length()));
Log.v(TAG, String.format("port is %d", address, port));
Log.v(TAG, String.format("InetAddress is [%s]",  InetAddress.getByName(address), port)));
Log.v(TAG, String.format("packet1 is [%s]; it's size is %d",  packet1, packet1.length()));

Log.v(TAG, String.format("socket is [%s]",  ChatService.socket.toString()));

或者,您可以通过调试器运行它。这真的会让你看到发生了什么。

【讨论】:

  • 消息是 [mssgyassine: hello];它的大小是 18 地址是 [192.168.93.103];它的大小是 14 端口是 5555 InetAddress 是 [/192.168.93.103] packet1 是 [java.net.DatagramPacket@430658b8];它的大小是 18
  • 那么剩下的就是 ChatService.socket 或者 send 方法中的东西了。是否有可能您没有在代码中的这一点将套接字设置为一个值?我添加了另一个日志行。记录套接字时的输出可能不是很有意义,但应该告诉您它是否为空;
  • 那么这就指向了根本问题。您的代码期望套接字此时可用,但事实并非如此。
【解决方案2】:

谢谢斯科特,我终于可以简单地解决它了!它只是创建服务器套接字的问题。我在 ClientThread 中添加了一个 DatagramPacket 作为属性,并更改了构造函数。 .

public class ClientThread extends Thread implements Runnable{
String address;
String message;
int port;
boolean broadcast;
public DatagramSocket socket;
public ClientThread(String address, String message, int port,boolean broadcast, DatagramSocket socket)
{   super();
    this.address = address;
    this.message = message;
    this.port = port;
    this.broadcast = broadcast;
    this.socket = socket;
}
public void run() {
    try {   
        DatagramPacket packet1 = new DatagramPacket(message.getBytes(), message.length(), InetAddress.getByName(address), port);
        socket.send(packet1);
    } catch (Exception e) {
        e.printStackTrace();

    }
    socket.close();
}    

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多