Android无法发送单播UDP

时间:2014-04-29 19:48:04

标签: android sockets networking udp

我有以下设置: 我的计算机是一个通过WiFi适配器的热点,其上运行着一个服务器应用程序(代码无关紧要,丑陋但我可以发布,如果它很重要)。我的电脑的IP地址是192.168.66.1。

我写了一个向它发送UDP数据包的android应用程序,如果我将它发送到255.255.255.255,该数据包只会出现在wireshark上。如果我尝试将目标更改为192.168.66.255或192.168.66.1,它就不会出现在wireshark上,并且设备上没有报告错误。 (我在尝试单播时也将套接字更改为广播(false))

这是不起作用的发送代码:

public class ClientThread implements Runnable {         

    public ClientThread()
    {
        super();                        
    }           

    private void sendCmd(DatagramSocket s, ByteArrayOutputStream cmd) throws Exception
    {
        InetAddress inet;
        inet = getBroadcastAddress(getApplicationContext());
        Log.d("ScreenToggler", inet.toString());
        //DatagramPacket dataPacket = new DatagramPacket(cmd.toByteArray(), cmd.toByteArray().length, InetAddress.getByName("255.255.255.255"), ScreenToggler.SERVERPORT);
        //s.setBroadcast(true);
        DatagramPacket dataPacket = new DatagramPacket(cmd.toByteArray(), cmd.toByteArray().length, InetAddress.getByName("192.168.66.1"), ScreenToggler.SERVERPORT);
        s.setBroadcast(false);
        s.send(dataPacket);
        Log.d("ScreenToggler", "Sent packet");
    }

    public void run() {                     
        DatagramSocket socket = null;


        try
        {
            try
            {                   
                socket = new DatagramSocket(ScreenToggler.SERVERPORT);
            }
            catch(Exception e)
            {
                Log.e("ScreenToggler", "S: Error", e);
                return;
            }

            Log.d("ScreenToggler", "C: Connecting...");

            System.out.println(CmdToSend.toByteArray().length);
            sendCmd(socket, CmdToSend);

            socket.close();
        }
        catch (Exception e)
        {
            Log.e("ScreenToggler", "S: Error", e);
            try
            {
                socket.close();
            }
            catch(Exception e2)
            {}
        }                                           
    }
}

当我尝试使用此代码发送时,没有异常发生,流程继续正常,并且wireshark上没有任何内容。没有任何迹象表明出现了问题 - 例如我的机器人拒绝发送数据包。

如果我取消注释两行

//DatagramPacket dataPacket = new DatagramPacket(cmd.toByteArray(), cmd.toByteArray().length, InetAddress.getByName("255.255.255.255"), ScreenToggler.SERVERPORT);
//s.setBroadcast(true);

并重新评论他们的两个相应的行,数据包出现在wireshark上,并在我的计算机上的服务器应用程序上正确接收。我的电脑的防火墙已关闭。

这是我的权限清单文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="zomg.screenshutter"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
    android:minSdkVersion="14"
    android:targetSdkVersion="19" />

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="zomg.screenshutter.ScreenToggler"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

我有其他可能相关的信息是我的android的IP地址是192.168.66.101,它识别192.168.66.1作为其网关(当我尝试通过wifi管理器获取网关地址时,它确实返回我的计算机的地址)。 / p>

我不知道我在这里缺少什么?

1 个答案:

答案 0 :(得分:0)

我刚刚建立了一个套接字类。我测试了它

如果你发送广播,你需要知道你的ip-address(192.168.178.14)和你的新掩码(255.255.255.0)上建立的braodcast地址。只需在shell中键入“ifconfig”,然后在“Bcast”后看到ip。你也需要一个端口号,对我而言总是9999(选择一个1024,因为下面的每个数字都保留给其他服务)

public class SocketService {
    private Handler mHandler;

    // threads
    private UDPReceiveThread mUDPReceiveThread;

    // UDP
    private DatagramSocket mUDPSendSocket;
    private DatagramPacket mUDPPacket;
    private byte[] mUDPSendData;

    public SocketService(Handler handler) {
            mHandler = handler;
            try {
                    mUDPReceiveThread = new UDPReceiveThread(9999);
                    mUDPReceiveThread.start();
            } catch (SocketException e) {
                    e.printStackTrace();
            }

            try {
                    mUDPSendSocket = new DatagramSocket();
            } catch (SocketException e) {
                    e.printStackTrace();
            }
    }

    public void close() {
            try {
                    mUDPSendSocket.close();
            } catch (IOException e) {
                    e.printStackTrace();
            }
    }

    public void writeUDP(String message, String address, int port) {
            if (null == mUDPSendData)
                    mUDPSendData = new byte[1024];

            if (null != mUDPSendSocket) {
                    InetAddress ipAddress;
                    try {
                            ipAddress = InetAddress.getByName(address);
                            mUDPSendData = message.getBytes();
                            mUDPPacket = new DatagramPacket(mUDPSendData, mUDPSendData.length, ipAddress, port);
                            new UDPSendThread().start();
                    } catch (Exception e) {
                            e.printStackTrace();
                    }
            }
    }

    private class UDPSendThread extends Thread {
            public void run() {
                    try {
                            mUDPSendSocket.send(mUDPPacket);
                    } catch (IOException e) {
                            e.printStackTrace();
                    }
            }
    }

    private class UDPReceiveThread extends Thread {
            private DatagramSocket tReceiveSocket;
            DatagramPacket tReceivePacket;
            private byte[] tReceiveData;
            private String tMessage = null;

            public UDPReceiveThread(int port) throws SocketException {
                    tReceiveSocket = new DatagramSocket(port);
                    tReceiveData = new byte[1024];
                    tReceivePacket = new DatagramPacket(tReceiveData, tReceiveData.length);
            }

            public void run() {
                    while (true) {
                            try {
                                    tReceiveSocket.receive(tReceivePacket);
                                    tMessage = new String(tReceivePacket.getData(), "UTF-8").substring(0, tReceivePacket.getLength());
                                    mHandler.obtainMessage(MainActivity.MESSAGE_NEW_UDP_DATA, tReceivePacket.getLength(), -1, tMessage).sendToTarget();
                            } catch (IOException e) {
                                    e.printStackTrace();
                            }
                    }

            }
    }

}

这是我使用类

的MainActivity
public class MainActivity extends Activity {
    private SocketService mService;

    private String mUdpSendIp = "192.168.178.255";

    //views
    private Button bUdpSend;

    //messages
    public static final int MESSAGE_NEW_UDP_DATA = 1;
    public static final int MESSAGE_NEW_TCP_DATA = 2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            mService = new SocketService(mHandler);

            //find views
            TextView tvUdpTitle = (TextView)findViewById(R.id.tv_udpTitle);
            bUdpSend = (Button)findViewById(R.id.b_udpSend);

            //configure views
            tvUdpTitle.setTextColor(getResources().getColor(R.color.textBlue));
            bUdpSend.setOnClickListener(new buttonListener());
    }

    @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;
    }

    public class buttonListener implements OnClickListener {
            @Override
            public void onClick(View v) {
                    if(v.equals(bUdpSend)) {
                            EditText etUdpMessage = (EditText)findViewById(R.id.et_udpMessage);
                            mService.writeUDP(etUdpMessage.getText().toString(), mUdpSendIp, 9999);
                    }
            }
    }

    private final Handler mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                    switch(msg.what) {
                    case MESSAGE_NEW_UDP_DATA:
                            String message = (String) msg.obj;
                            TableLayout tl_udpReceive = (TableLayout) findViewById(R.id.tl_udpReceive);

                            TableRow tr = new TableRow(getApplicationContext());
                            TextView tvNewMessage = new TextView(getApplicationContext());

                            tvNewMessage.setText(message);
                            tvNewMessage.setTextSize(16);
                            tvNewMessage.setTextColor(getApplicationContext().getResources().getColor(R.color.textBlue));
                            tr.addView(tvNewMessage);
                            tl_udpReceive.addView(tr);
                            final ScrollView tmp = (ScrollView)tl_udpReceive.getParent();
                            tmp.post(new Runnable() {            
                                @Override
                                public void run() {
                                    tmp.fullScroll(View.FOCUS_DOWN);              
                                }
                            });

                            break;
                    }
            }
    };

}