class7-intro-to-tcp-ip-and-socket-programming

advertisement
Introduction to Socket Programming in
Android
Jules White
Bradley Dept. of Electrical and
Computer Engineering
Virginia Tech
julesw@vt.edu
What is a Socket?
• A socket is a software endpoint that can plug into or be plugged into
to create a bi-directional communication link between software
processes
• A socket is a common interface for performing network
communication
• Underneath the hood, Android’s HTTP client library is using sockets
to send and receive data
Socket
Socket
Java Sockets
• In Java, a ServerSocket can receive new connections from a client
• A client connects to a remote ServerSocket through a standard
Socket instance
• When the server receives the connection, it talks to the client using a
standard socket
Socket
Server
Socket
InputStreams in Java
• An InputStream is a stream of incoming byte data
• An InputStream can be obtained from a Socket by using the
getInputStream() method
• In order to read from a stream, you must create a byte buffer to read
in data
• Each call to read on an InputStream fills your buffer with data and
returns the number of bytes read
InputStream in = somesocket.getInputStream();
byte[] buffer = new byte[1024];
int bytesread = 0;
while( (bytesread = in.read(buffer,0,buffer.length)) != -1){
//the buffer has been filled, do something with the data
}
OutputStreams in Java
• An OutputStream is a stream of outgoing byte data
• An OutputStream can be obtained from a Socket by using the
getOutputStream() method
• You can write data to a stream by passing in a byte buffer of data
• You should use the flush() method if you want to make sure that the
data you have written has been output to disk or sent to the other
end of the socket
OutputStream out = somesocket.getOutputStream();
out.write(“Hello Socket”.getBytes());
out.flush();
byte[] buffer = new byte[1024];
//fill the buffer
out.write(buffer,0,buffer.length);
out.close();
A Simple Socket-based Server
• Example:
public class ExampleServerSocket{
public void start() throws Exception {
//Create a ServerSocket on port 9090
ServerSocket serversock = new ServerSocket(9090);
while(running){
Socket client = serversock.accept();
OutputStream out = client.getOutputStream();
InputStream in = client.getInputStream();
//read and write some data from the streams
out.close();
in.close();
client.close();
}
}
}
A Simple Socket-based Client
• Example:
public class ExampleSocketClient{
public void start() throws Exception {
Socket server = Socket(
“127.0.0.1”, //the host or IP address to connect to
9090 //the port to connect to on that host
);
OutputStream out = server.getOutputStream();
InputStream in = server.getInputStream();
out.write(“foo”.getBytes());
out.flush(); //VERY IMPORTANT
// read some stuff….
in.close();
out.close();
server.close();
}
}
Threading in Android
• Socket and streaming network operations may take a significant
amount of time
• You cannot block the GUI thread for too long in Android
• In order to connect as a client or receive connections, you must
spawn threads to handle the communication
• To spawn a Thread in Java, create a class that implements runnable
and construct a new Thread object with it
public class LongRunningWork implements Runnable {
public void run(){
//do long running stuff here
}
public void threadMe(){
Thread t = new Thread(this);
t.start();
}
}
What Should You Thread?
• For the client, you need to thread the instantiation of the Socket and
all read/write operations to it when it is connected
• For the server, you need to have multiple threads
• Some thread needs to call accept()
• Some thread needs to manage reading/writing data for each client
after a socket is returned from accept
• The threading architecture is very important
• Possible threading approaches:
• Thread per connection
• Eager spawning / thread pools
• Half-sync / Half-async
• Leader / Followers
Synchronizing the GUI Thread with Others
• Once approach that we have learned is to use a Handler to
coordinate the exchange of work between the GUI and other threads
• Another approach is to use the Android AsyncTask class
• Android automatically manages the creation of Threads for
AsyncTasks
• An AsyncTask has three key methods that each run in a different
thread context:
• doInBackground() – runs in a NON-GUI thread
• onProgressUpdate() – runs in the GUI thread
• onPostExecute() – runs in the GUI thread
• You create a subclass of AsyncTask and Android automatically runs
each of your implementations of these methods in the correct thread
context
The AsyncTask Template Parameters
• The types specified in the template parameters correspond to the parameter type of the doInBackground
method, the type for the parameter to onProgressUpdate, and the type that is returned by doInBackground
public class HttpTask extends AsyncTask<String, Integer, Long> {
…..
protected Long doInBackground(String... params) {
//this runs in a background thread from the pool
….
publishProgress(some_new_progress_value);
….
return new Long(0);
}
protected void onProgressUpdate(Integer... progress) {
//this runs in the UI thread
//this is where you notify any callbacks that require incremental progress
}
protected void onPostExecute(Long result) {
//this runs in the UI thread
//this is where you would invoke your callback to the entity that created the request
}
}
AsyncTask Example
public class HttpTask extends AsyncTask<String, Float, String> {
…..
protected Long doInBackground(String... params) {
Socket socket = new Socket(some_host,some_port);
InputStream in = socket.getInputStream();
byte[] buff = new byte[1024];
float expectedsize = 12341234;
int read = 0;
float totalread = 0;
while( (in.read(buff,0,buff.length)) != -1){
totalread += read;
publishProgress(totalread/expectedsize);
}
return “It worked!”;
}
protected void onProgressUpdate(Float... progress) {
//this runs in the UI thread
//this is where you notify any callbacks that require incremental progress
someProgressBar_.setValue(progress * 100);
}
protected void onPostExecute(String result) {
//this runs in the UI thread
//this is where you would invoke your callback to the entity that created the request
someTextView.setText(result);
}
}
Download