2

I need to send a command from an android phone, via wifi, to a router, through a wire, to a "cable box" <--- just assume cable box for now. When sending the command from my laptop, I get a nice healthy flood of data on my wireshark reading. Also, the cable box responds and does what it is told. However, as soon as I try to put the App on my phone and use it, nothing happens. If I send the command from my phone to my computer I get 2 empty packets sent back and forth between my phone and computer. What am I doing wrong here? I've been struggling with this for 3 days now.

import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.util.ArrayList;

public class TCPRunnable implements Runnable{
    private final String ip;
    private final int port;
    private final ArrayList<String> commands;

//<editor-fold defaultstate="collapsed" desc="Constructors">
    @Deprecated
    public TCPRunnable(String ip,int port,ArrayList<String> Cmds){
        this.ip=ip;
        this.port=port;
        this.commands = Cmds;
    }
    public TCPRunnable(String ip,int port,String Cmd){
        this.ip=ip;
        this.port=port;
        this.commands = new ArrayList<String>();
        this.commands.add(Cmd);
    }
//</editor-fold>

//<editor-fold defaultstate="collapsed" desc="Static Properties">

//</editor-fold>

//<editor-fold defaultstate="collapsed" desc="Instance Properties">

//</editor-fold>

    public void run() {
        try {
            InetAddress serverAddr = InetAddress.getByName(this.ip);
            SocketAddress socketadd= new InetSocketAddress(serverAddr,port);

            Log.d("TCP","R: Making the socket.");
            Socket socket = new Socket();
                //new Socket();//
            Log.d("TCP","R: Connecting...");
            socket.connect(socketadd, 1500);

        //  PrintWriter out = new PrintWriter (new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true);

            InputStream socketReader = socket.getInputStream();
            OutputStream socketWriter = socket.getOutputStream();
             try {
                for (int i = 0; i < commands.size();i++){
                    String Cmd = commands.get(i);
                    Log.d("TCP","R: Sending: '"+Cmd+"'");
                    byte [] iByte;
                    byte[] oByte = new byte[100];//in 32 bit signed integers
                    int CmdLen = 0;
                    CmdLen = commands.get(i).length();
                    oByte[0] = (byte) Integer.parseInt("AF", 16);
                    oByte[1] = (byte) Integer.parseInt("FA", 16);
                    oByte[2] = (byte) Integer.parseInt("F0", 16);
                    oByte[3] = (byte) (255-oByte[2]);
                    oByte[4] = (byte) (Cmd.length() +2);
                    oByte[5] = (byte) (255-oByte[4]);
                    oByte[6] = (byte) Integer.parseInt("07", 16);
                    iByte = Cmd.getBytes();
                    System.arraycopy(iByte, 0, oByte, 7, Cmd.length());
                    oByte[7+CmdLen] = (byte) Integer.parseInt("00",16);
                    oByte[8+CmdLen] = (byte) Integer.parseInt("00",16);

                    Object [] data = new Object [3];
                    data[0]=oByte;
                    data[1]=0;
                    data[2]=(9 + CmdLen);
                    //ping(IP,PORT);
                    //disconnect();
                    //connect();
                    socketWriter.write((byte[])data[0],(Integer)data[1],(Integer)data[2]);
                    socketWriter.flush();
                    Log.d("TCP","R: Sent.");
                    //Thread.sleep(500L);
                }
            }catch (Exception ex){
                Log.e("TCP", "S: Sending failed: "+ex);
            }finally{

                socketWriter.flush();
                socketWriter.close();
                socket.close();
                Log.d("TCP","R: Done.");
             }

        } catch (IOException ex) {
            Log.e("IOEXCEPTION",""+ex);
        }




    }
//<editor-fold defaultstate="collapsed" desc="Static Methods">

//</editor-fold>

//<editor-fold defaultstate="collapsed" desc="Instance Methods">

//</editor-fold>

//<editor-fold defaultstate="collapsed" desc="Accessors">

//</editor-fold>

}

Edit: I still can't send data. but at least I know why 'no data is sent' now. It was because I was sending data to a laptop and not the machine itself. Second Edit where my code comments out //sleep(500L);, It should be uncommented. Otherwise you send data too quickly to receive a response.

Pangamma
  • 731
  • 12
  • 28

2 Answers2

1

Are those two packets like this?

SYN -->
    <-- SYN ACK

Isn't there a third ACK going back?

I see you issue a flush on the stream, but I'm not sure if the OS honors that request. Can you try sending more data, like some kilobytes, and see if anything comes out? A wireshark capture would also be useful.

Update

In the pastebin, you try to connect to .32 which is your laptop then. In the successful case, .32 connects to .42. Obviously if port 20036 is not open on your laptop and doesn't run the service, you can't connect to it.

There are some ways to work around this:

A) If using wireless connection on laptop and phone, you might be able to put the laptop into promiscuous mode to listen to all packages. Google helps here.

B) You may set up the laptop to redirect the connection to the box, so you can sniff on the laptop. This depends on the laptop OS.

  • For Linux you may use something like redir
  • It seems both Linux and Windows has rinetd

C) Communicate directly with the box, and root your Android device then install a packet capture software directly on the Android device.

Update

rinetd for windows:

rinetd.conf:

0.0.0.0 port_to_listen_on_laptop box_ip_address target_box_port

Then:

rinetd.exe -c rinetd.conf
Community
  • 1
  • 1
ron
  • 9,262
  • 4
  • 40
  • 73
  • Yes! They are exactly like that. but there is no third ACK going back.http://puu.sh/14PpG As for wireshark, what would be the best way to upload it? I'm hoping for a more permanent solution than puu.sh so future viewers can use this post to get help. – Pangamma Sep 13 '12 at 23:15
  • No, it is an `RST` coming back, which is Not A Good Thing(TM). The server abruptly closes the connection. What could cause it? Firewall, etc? Upload cap file to dropbox if you have, or google popped up http://minus.com/. – ron Sep 13 '12 at 23:20
  • Maybe this helps: http://stackoverflow.com/questions/251243/what-causes-a-tcp-ip-reset-rst-flag-to-be-sent – ron Sep 13 '12 at 23:25
  • It does clarify some things. Alright, so the other device only listens on port 20036. but... wtf, I'm trying to connect to my laptop. This makes little sense. Except that my laptop is not set up running a server. It is simply receiving whatever I throw at it. You mentioned a third packet. Does this mean my phone and my target device have to complete a "handshake" before any real data can be sent? (I do not have access to the server sided source code, so I'm working with a closed box right now. If I send a packet directly to the "box" I won't have a way to monitor it.) – Pangamma Sep 13 '12 at 23:35
  • http://minus.com/lYXXCOd48Ixtd This is what I receive when going from my laptop to the box. – Pangamma Sep 13 '12 at 23:45
  • Updated the answer with redirecting tools. – ron Sep 14 '12 at 05:54
  • The OS never even sees the `flush()`. It's just another `send()` to the OS, maybe nothing if there was nothing to flush. – user207421 Sep 14 '12 at 10:24
  • @Pangamma If you got an RST coming back you should also have got a `ConnectionException`. Did you swallow it? And 1500ms is far too short for a connect timeout. 10s would be more like it. – user207421 Sep 14 '12 at 10:24
  • 1
    If on your laptop there is no server listening on the port you are using, the two segments you captured are correct and expected. Client sends SYN, server responds with RST indicating it does not listen on this port. Why the application cannot communicate with the cablebox? Maybe your router defines two separate local networks one for WIFI one for a cable connection. If so, maybe the IP address of the cablebox you are using in the android app is not the IP address of the router in the WIFI network but in the cable network? – Jan Wrobel Sep 14 '12 at 10:57
  • Jan: As I understood, the OP realized that he tried to communicate with the laptop by mistake instead of the box. He wants to go through the laptop to be able to capture the packets for debugging purpose. Correct me if I'm wrong. – ron Sep 14 '12 at 16:59
  • @EJP I just made it so I could capture errors and see them on my phone. Yes, it is a ConnectionException. Also I set the new timeout to 10,000ms or 10s like you suggested. – Pangamma Sep 14 '12 at 17:08
  • @Jan- I added a ping feature, and I can ping both my laptop and the box. When I sent the signal to the box, it came back with no errors (unlike when I ping my computer.) So I have reason to suspect... it is sending properly, but maybe some of the command gets confused along the way. I'll research how to capture packets from the phone-->box-->phone connection on my laptop. (If possible) I also captured the command being sent out and displayed it. It is correct. Still seeing no changes on the cable box. – Pangamma Sep 14 '12 at 17:20
  • @ron Kind of. I knew I was communicating with the laptop. That was for debugging. Now I realize communicating with the laptop is not going to work because I would need a server running on my laptop. Trying to get wireshark to work on my phone. Google did not make this easy. lol. – Pangamma Sep 14 '12 at 18:46
  • Pangamma: How about installing the rinetd service on your laptop I included in the answer? It can forward the traffic to the box and you can sniff on the laptop. – ron Sep 14 '12 at 19:47
  • @ron rinetd installation instructions were only made for Linux. I double clicked the rinetd.exe file, a black box appeared, then disappeared as if nothing happened. – Pangamma Sep 14 '12 at 20:43
  • @Pangamma typically on Windows you do `cmd` then start the stuff from the console, so you see the messages it prints. I updated `rinetd` instructions for windows. Works fine for me (although I run Linux and tried it with Wine). – ron Sep 15 '12 at 05:03
0

Not sure if this was the only change I had to make, but I do know that uncommenting the "Thread.sleep(500L);" helped a lot. The sockets were most likely being closed before any data was able to be sent. So some time was needed to allow the commands to go through before closing the socket.

Pangamma
  • 731
  • 12
  • 28