Why my UDP client/server datagram is not operating

2019-03-07 04:37发布

问题:

I set up a simple UDP client/server datagram between two applications: Android-Java-Client and Windows-C#-Server. This is my first ever Java programming and Android applications so the solution might be obvious. So I succeeded in sending a packet from the client to the server. However, I couldn't send back from the server to the client.

I am trying to send a confirmation message from the server back to the client. I tried merging C# Client code with the existing C# Server code but it crashes once the server receives its first message System.ObjectDisposedException. I deleted and started all over again "See edited if you want". Now, I send successfully to the server but nothing is received and nothing gets displayed on the Java Client Side. I know that I can (or maybe should) use the same socket to send back to the client. Where is my mistake? Please and Thanks.

  • I tried putting the whole NetworkThread in the OnTouchListener
  • I tried breaking down SendUdpMessage() into two, one to send and one to receive
  • I tried the below answer

And I still can't make it work :(

C# Server Side:

// This class is responsible of running the server side on the PC. 
class UdpServer
{
    static void Main(string[] args)
    {
        byte[] data = new byte[1024];
        UdpClient serverSocket = new UdpClient(15000);
        int i = 0;

        while (true)
        {
            Console.WriteLine("Waiting for a UDP client...");
            IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
            data = serverSocket.Receive(ref sender);

            string stringData = Encoding.ASCII.GetString(data, 0, data.Length);
            Console.WriteLine("Response from " + sender.Address);
            Console.WriteLine("Message " + i++ + ": " + stringData + "\n");

            // Here I am sending back
            byte[] data2 = Encoding.ASCII.GetBytes("Response");
            serverSocket.Send(data2, 8, sender);
        }

    }
}

Java Client Side: A button calls a function to send a UDP message, and assign the response into a global variable which then I try to display on the screen via a TextBox

    public class MainActivity extends AppCompatActivity {

    String message;
    String Response;

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

        // Button Declaration
        final TextView TextOne = (TextView) findViewById(R.id.StatusText);
        Button LftBtn = (Button) findViewById(R.id.LeftButton);
        // ...
        // other code here (button declaration and event handlers
        // ...

        // Left Button Click
        LftBtn.setOnTouchListener(
                new Button.OnTouchListener() {
                    public boolean onTouch(View v, MotionEvent event) {
                        if (event.getAction() == MotionEvent.ACTION_DOWN) {
                            //Button pressed
                            TextOne.setText("Left");
                            message = "Left";
                            SendUdpMsg(message);
                            TextOne.setText(Response);
                            return true;
                        } else if (event.getAction() == MotionEvent.ACTION_UP) {
                            //Button released do nothing
                            return true;
                        }
                        return false;
                    }//onTouch
                });//setOnTouchListener
    }

    // This function is responsible for sending a udp packet to a hardCoded IP below. Returns nothing and takes a string(the message) as a parameter.
    public void SendUdpMsg(final String msg)
    {
        Thread networkThread = new Thread() {

            // No local Host 127.0.0.1 in Android
            String host = "192.168.200.3"; // my actual IP
            int port = 15000;
            DatagramSocket dsocket = null;
            String Response = "1";

            public void run() {
                try {
                    // Get the Internet address of the specified host
                    InetAddress address = InetAddress.getByName(host);

                    // wrap a packet
                    DatagramPacket packet = new DatagramPacket(
                            msg.getBytes(),
                            msg.length(),
                            address, port);

                    // Create a datagram socket, send the packet through it, close it.
                    dsocket = new DatagramSocket();
                    dsocket.send(packet);

                    // Here, I am receiving the response?
                    byte[] buffer = new byte[1024];
                    DatagramPacket packet2 = new DatagramPacket(buffer, buffer.length);
                    dsocket.receive(packet2);
                    Response = new String(buffer, 0, packet2.getLength());
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run()
                        {
                            // I can't use this since TextOne is a local variable in the above function
                            //TextOne.setText(Response);
                        }
                    });
                    dsocket.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }//catch
            }//run
        };// Networkthread
        networkThread.start();//networkThread.start() 
    }       
}

回答1:

The network code works, the problem is that your are not waiting for the response, i.e. the SendUdpMsg method can not return the response immediately, it should be pushed by the background thread. For example :

dsocket.receive(packet2);
Response = new String(buffer, 0, packet2.getLength());

// we received the response
// but since we are running on a background thread, we can not touch the UI
runOnUiThread(new Runnable() {
    @Override
    public void run() {
        // this is executed on the main (UI) thread
        TextOne.setText(Response);                        }
});

dsocket.close();

Having to work on a background thread and handle the results on the main thread is a common pattern. Android provides a few tools like Handler or AsyncTask



回答2:

So I added this into my SendUdpMsg():

runOnUiThread(new Runnable() {
    @Override
    public void run()
           {
                 final TextView TextOne = (TextView) findViewById(R.id.StatusText);
                 TextOne.setText(Response);
           }
});`

And finally it worked ! On button click I successfully send message and receive Response .

Mission: I want to click my mobile to start streaming live video from the laptop's webcam, and display it into my mobile's screen.

Request: Is my approach of this Two Way Communication is good? If no what is the best?