Communicating with a server socket

Một phần của tài liệu Manning unlocking android a developers (Trang 198 - 201)

A server socket is a stream that you can read or write raw bytes to, at a specified IP address and port. This lets you deal with data and not worry about media types, packet sizes, and so on. This is yet another network abstraction intended to make the job of the programmer a bit easier. The philosophy that sockets take on, that everything should look like file I/O to the developer, comes from the POSIX family of standards and has been adopted by most major operating systems in use today.

We will move on to higher levels of network communication in a bit, but first we will start with a raw socket. For that we need a server listening on a particular port.

The EchoServer code shown in listing 6.2 fits the bill. This isn’t an Android-specific Listing 6.1 The onStart method of the NetworkExplorer main Activity

Obtain manager from Context

B

C Get NetworkInfo

Figure 6.2 The output of the NetworkInfo toString method.

class; rather it’s just an oversimplified server that can run on any host machine with Java. We’ll later connect to it from an Android client.

public final class EchoServer extends Thread { private static final int PORT = 8889;

private EchoServer() {}

public static void main(String args[]) { EchoServer echoServer = new EchoServer();

if (echoServer != null) { echoServer.start();

} }

public void run() { try {

ServerSocket server = new ServerSocket(PORT, 1);

while (true) {

Socket client = server.accept();

System.out.println("Client connected");

while (true) {

BufferedReader reader =

new BufferedReader(new InputStreamReader(

client.getInputStream()));

System.out.println("Read from client");

String textLine = reader.readLine() + "\n";

if (textLine.equalsIgnoreCase("EXIT\n")) { System.out.println("EXIT invoked, closing client");

break;

}

BufferedWriter writer = new BufferedWriter(

new OutputStreamWriter(

client.getOutputStream()));

System.out.println("Echo input to client");

writer.write("ECHO from server: "

+ textLine, 0, textLine.length() + 18);

writer.flush();

}

client.close();

}

} catch (IOException e) { System.err.println(e);

} } }

The EchoServer class we are using is fairly basic Java I/O. It extends Thread and implements runB, so that each client that connects can be handled in its own con- text. Then we use a ServerSocketC to listen on a defined port. Each client is then

Listing 6.2 A simple echo server for demonstrating socket usage

Implement run to start

B

Use

java.net.ServerSocket

C

D Use java.net.Socket for each client

Read input with BufferedReader

E

F

EXIT, break the loop

G Send echo with BufferedWriter

an implementation of a Socket D. The client input is fed into a BufferedReader that each line is read from E. The only special consideration this simple server has is that if the input is EXIT, it breaks the loops and exits F. If the input does not prompt an exit, the server echoes the input back to the client’s OuputStream with a BufferedWriterG.

This is a good, albeit intentionally very basic, representation of what a server does.

It handles input, usually in a separate thread, then responds to the client based on the input. To try out this server before using Android, you can telnet to the specified port (after the server is running, of course) and type some input; if all is well it will echo the output.

To run the server you need to invoke it locally with Java. It has a main method, so it will run on its own; start it from the command line or from your IDE. Be aware that when you connect to a server from the emulator, this or any other, you need to con- nect to the IP address of the host you run the server process on, not the loopback (not 127.0.0.1). The emulator thinks of itself as 127.0.0.1, so use the non-loopback address of the server host when you attempt to connect from Android. (You can find out the IP address of the machine you are on from the command line by entering ifconfig on Linux or Mac and ipconfig on Windows.)

The client portion of this example is where NetworkExplorer itself begins, with the callSocket method of the SimpleSocket Activity shown in listing 6.3.

public class SimpleSocket extends Activity {

. . . View variable declarations omitted for brevity @Override

public void onCreate(final Bundle icicle) { super.onCreate(icicle);

this.setContentView(R.layout.simple_socket);

. . . View inflation omitted for brevity

this.socketButton.setOnClickListener(new OnClickListener() { public void onClick(final View v) {

socketOutput.setText("");

String output = callSocket(

ipAddress.getText().toString(), port.getText().toString(),

socketInput.getText().toString());

socketOutput.setText(output);

} });

}

private String callSocket(String ip, String port, String socketData) { Socket socket = null;

BufferedWriter writer = null;

BufferedReader reader = null;

String output = null;

Listing 6.3 An Android client invoking a raw socket server resource, the echo server

Use callSocket method

B

C Set view output

try {

socket = new Socket(ip, Integer.parseInt(port));

writer = new BufferedWriter(

new OutputStreamWriter(

socket.getOutputStream()));

reader = new BufferedReader(

new InputStreamReader(

socket.getInputStream()));

String input = socketData;

writer.write(input + "\n", 0, input.length() + 1);

writer.flush();

output = reader.readLine();

this.socketOutput.setText(output);

// send EXIT and close

writer.write("EXIT\n", 0, 5);

writer.flush();

. . . catches and reader, writer, and socket closes omitted for brevity . . . onCreate omitted for brevity

return output;

}

Here we use the onCreate method to call a private helper callSocket method B

and set the output to a TextView C. Within the callSocket method we create a Socket to represent the client side of our connection D, and we establish a writer for the input E and a reader for the output F. With the housekeeping taken care of, we then write to the socket G, which communicates with the server, and get the output value to return H.

A socket is probably the lowest-level networking usage in Android you will encoun- ter. Using a raw socket, while abstracted a great deal, still leaves many of the details up to you (especially server-side details, threading, and queuing). Although you may run up against situations in which either you have to use a raw socket (the server side is already built) or you elect to use one for one reason or another, higher-level solutions such as leveraging HTTP normally have decided advantages.

Một phần của tài liệu Manning unlocking android a developers (Trang 198 - 201)

Tải bản đầy đủ (PDF)

(418 trang)