Incorporating Socket Programming into your Applications

来源:互联网 发布:淘宝buy 宣传视频 编辑:程序博客网 时间:2024/05/21 22:35

http://thinkandroid.wordpress.com/2010/03/27/incorporating-socket-programming-into-your-applications/

Hey everyone,

Haven’t posted in a while. Here’s something new that I came across and thought might be useful. This post is for anyone who has wanted to create an application that could communicate with another phone running your same application.

The idea involves Socket Programming and basically letting one phone be the “server” and the other phone be the “client”. Now, I don’t know if this is standard practice for letting two phones communicate with one another, but it worked for me in a new application that I’ve been working on, and so here it is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
publicclass ServerActivity extends Activity {
 
    privateTextView serverStatus;
 
    // DEFAULT IP
    publicstatic String SERVERIP = "10.0.2.15";
 
    // DESIGNATE A PORT
    publicstatic final int SERVERPORT = 8080;
 
    privateHandler handler = newHandler();
 
    privateServerSocket serverSocket;
 
    @Override
    protectedvoid onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.server);
        serverStatus = (TextView) findViewById(R.id.server_status);
 
        SERVERIP = getLocalIpAddress();
 
        Thread fst =new Thread(new ServerThread());
        fst.start();
    }
 
    publicclass ServerThread implements Runnable {
 
        publicvoid run() {
            try{
                if(SERVERIP != null) {
                    handler.post(newRunnable() {
                        @Override
                        publicvoid run() {
                            serverStatus.setText("Listening on IP: "+ SERVERIP);
                        }
                    });
                    serverSocket =new ServerSocket(SERVERPORT);
                    while(true) {
                        // LISTEN FOR INCOMING CLIENTS
                        Socket client = serverSocket.accept();
                        handler.post(newRunnable() {
                            @Override
                            publicvoid run() {
                                serverStatus.setText("Connected.");
                            }
                        });
 
                        try{
                            BufferedReader in =new BufferedReader(new InputStreamReader(client.getInputStream()));
                            String line =null;
                            while((line = in.readLine()) != null) {
                                Log.d("ServerActivity", line);
                                handler.post(newRunnable() {
                                    @Override
                                    publicvoid run() {
                                        // DO WHATEVER YOU WANT TO THE FRONT END
                                        // THIS IS WHERE YOU CAN BE CREATIVE
                                    }
                                });
                            }
                            break;
                        }catch (Exception e) {
                            handler.post(newRunnable() {
                                @Override
                                publicvoid run() {
                                    serverStatus.setText("Oops. Connection interrupted. Please reconnect your phones.");
                                }
                            });
                            e.printStackTrace();
                        }
                    }
                }else {
                    handler.post(newRunnable() {
                        @Override
                        publicvoid run() {
                            serverStatus.setText("Couldn't detect internet connection.");
                        }
                    });
                }
            }catch (Exception e) {
                handler.post(newRunnable() {
                    @Override
                    publicvoid run() {
                        serverStatus.setText("Error");
                    }
                });
                e.printStackTrace();
            }
        }
    }
 
    // GETS THE IP ADDRESS OF YOUR PHONE'S NETWORK
    privateString 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()) { returninetAddress.getHostAddress().toString(); }
                }
            }
        }catch (SocketException ex) {
            Log.e("ServerActivity", ex.toString());
        }
        returnnull;
    }
 
    @Override
    protectedvoid onStop() {
        super.onStop();
        try{
             // MAKE SURE YOU CLOSE THE SOCKET UPON EXITING
             serverSocket.close();
         }catch (IOException e) {
             e.printStackTrace();
         }
    }
 
}

Before moving on to the client side of things, let’s just try and digest this together (for those who are familiar to Socket Programming much of this will look familiar – this is simply meant to be an integration of Socket Programming with the Android platform). In our onCreate() method we first retrieve the IP address that the phone designated as the “server” is on. This will work regardless of whether you’re on WIFI or 3G and is required for the client to connect to you. As soon as I get the IP address I kick off the server thread. Notice that it’s important you open and close all of the connections in a thread as the call:

1
Socket client = serverSocket.accept();

is blocking / synchronous / will stop the progression of your code until an incoming client is found. You definitely don’t want to put this on the UI thread as it will completely choke up your application, and so we throw it into a background thread. Now, the thread itself is pretty self explanatory. Notice how all of the serverStatus text updates are wrapped around handlers (this is necessary as you can’t touch views in the UI from a different thread without a handler). Then, once the client is retrieved, we open an inputStream() from the client and use a BufferedReader to retrieve incoming messages from the client.

This is where you can be creative.

You can do pretty much whatever you want at this point. Namely, you could create a mini scripting language (i.e. send messages like “GO BACK”, “TURN LEFT”, “START MUSIC”, “GO TO URL xxx”, etc) and have the server phone respond to those messages, and you could even have the server write messages to the client as well and have the client respond to those messages. Basically, everything before hand was just the annoying technical stuff that is required for the connection between the two phones to get established – once it is established you can send whatever form of data between the two phones as you’d like and this is where you can have fun in your future applications.

The last thing to notice is just that we override onStop() to close the serverSocket. Again, the serverSocket.accept() call is blocking, and so if we don’t close the serverSocket upon stopping the Activity it will actually continue to listen for incoming clients (until your phone kills that thread of course) and this can be problematic as it will block all future attempts to connect to the port number you designated.

Now for the client side of things:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
publicclass ClientActivity extends Activity {
 
    privateEditText serverIp;
 
    privateButton connectPhones;
 
    privateString serverIpAddress = "";
 
    privateboolean connected = false;
 
    privateHandler handler = newHandler();
 
    @Override
    protectedvoid onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.client);
 
        serverIp = (EditText) findViewById(R.id.server_ip);
        connectPhones = (Button) findViewById(R.id.connect_phones);
        connectPhones.setOnClickListener(connectListener);
    }
 
    privateOnClickListener connectListener = newOnClickListener() {
 
        @Override
        publicvoid onClick(View v) {
            if(!connected) {
                serverIpAddress = serverIp.getText().toString();
                if(!serverIpAddress.equals("")) {
                    Thread cThread =new Thread(new ClientThread());
                    cThread.start();
                }
            }
        }
    };
 
    publicclass ClientThread implements Runnable {
 
        publicvoid run() {
            try{
                InetAddress serverAddr = InetAddress.getByName(serverIpAddress);
                Log.d("ClientActivity","C: Connecting...");
                Socket socket =new Socket(serverAddr, ServerActivity.SERVERPORT);
                connected =true;
                while(connected) {
                    try{
                        Log.d("ClientActivity","C: Sending command.");
                        PrintWriter out =new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket
                                    .getOutputStream())),true);
                            // WHERE YOU ISSUE THE COMMANDS
                            out.println("Hey Server!");
                            Log.d("ClientActivity","C: Sent.");
                    }catch (Exception e) {
                        Log.e("ClientActivity","S: Error", e);
                    }
                }
                socket.close();
                Log.d("ClientActivity","C: Closed.");
            }catch (Exception e) {
                Log.e("ClientActivity","C: Error", e);
                connected =false;
            }
        }
    }
}

Overall pretty simple. Just create some kind of EditText field that allows the user to input the correct IP address (which should be showing on the server phone) and then some kind of button that grabs the inputted IP address and tries to kick off a client thread which attempts to connect to that IP address on the specified port. Notice that the port numbers have to be the same in addition to the IP address. Once a connection has been made then everything else is pretty simple – just create an OutputStreamWriter and a BufferedWriter that allows you to send messages to the server. Then once the server receives those messages, it can respond to them in whatever way you want it to!

So yes, basically this code snippet / example is for anyone who wants to write some kind of application that works best when two phones are connected or talking to each other. Again, I’m not sure if this is how you’re supposed to go about it, but after searching for a while and eventually giving up and then finally coming across this Socket Programming idea in one of my classes, it seems like this method at least works!

So yes, happy coding everyone and hope this was interesting/helpful.

- jwei


原创粉丝点击