import java.net.*;
import java.util.*;
import java.io.*;
// Make an HTTP 1.0 post
public class HTTPForm extends Properties {
public boolean send(String page, OutputStream outstr) throws IOException
{
StringBuffer data=new StringBuffer();
String headers;
Enumeration i=keys();
while (i.hasMoreElements()) {
String key=(String)i.nextElement();
data.append(URLEncoder.encode(key)
+ "=" +
URLEncoder.encode((String)get(key))+
"&");
}
data.deleteCharAt(data.length()-1); // remove last &
headers="POST " + page + " HTTP/1.0\r\n"+
"Content-Type: application/x-www-form-urlencoded\r\n" +
"Content-Length: " + data.length() + "\r\n\r\n";
outstr.write(headers.getBytes());
outstr.write(data.toString().getBytes());
return true;
}
// Test main -- duplicates MailFind
public static void main(String args[]) throws Exception {
HTTPForm test=new HTTPForm();
Socket sock=new Socket("new.usps.com",80);
OutputStream output=sock.getOutputStream();
InputStream input=sock.getInputStream();
test.put("tracknbr",args[0]);
test.send("/cgi-bin/cttgate/ontrack.cgi",output);
// For this example, just dump results
int c;
do {
c=input.read();
if (c!=-1) System.out.print((char)c);
} while (c!=-1);
sock.close();
}
}
Socket sock=new Socket("www.google.com",80);
OutputStream str = sock.getOutputStream();
InputStream istr=sock.getInputStream();
String request;
String data;
data="";
// Set up request
request="GET /intl/zh-CN/ HTTP/1.0\r\n";
request+="Content-Type: application/x-www-form-urlencoded\r\n";
request+="Content-Length: " + (data.length())+"\r\n\r\n";
request+=data;
// Write it out
str.write(request.getBytes());
// For this example, just dump results
int c;
do {
c=istr.read();
if (c!=-1) System.out.print((char)c);
} while (c!=-1);
sock.close();
}
//
Listing 34.1
Source Code for ReadThread.java
import java.net.*; import java.lang.*; import java.io.*; /** * A thread dedicated to reading data from a socket connection. */
public class ReadThread extends Thread { protected Socket connectionSocket; // the socket you are reading from protected DataInputStream inStream; // the input stream from the socket protected ReadCallback readCallback; /** * Creates an instance of a ReadThread on a Socket and identifies the callback * that will receive all data from the socket. * * @param callback the object to be notified when data is ready * @param connSock the socket this ReadThread will read data from * @exception IOException if there is an error getting an input stream * for the socket */ public ReadThread(ReadCallback callback, Socket connSock) throws IOException { connectionSocket = connSock; readCallback = callback; inStream = new DataInputStream(connSock.getInputStream()); } /** * Closes down the socket connection using the socket's close method */ protected void closeConnection() { try { connectionSocket.close(); } catch (Exception oops) { } stop(); } /** * Continuously reads a string from the socket and then calls dataReady in the * read callback. If you want to read something other than a string, change * this method and the dataReady callback to handle the appropriate data. */ public void run() { while (true) { try { // readUTF reads in a string String str = inStream.readUTF(); // Notify the callback that you have a string readCallback.dataReady(str); } catch (Exception oops) { // Tell the callback there was an error readCallback.dataReady(null); } } } }
Listing 34.2 shows the ReadCallback interface, which must be implemented by a class to receive data from a ReadThread object.
Listing 34.2
Source Code for ReadCallback.java
/** * Implements a callback interface for the ReadConn class */ public interface ReadCallback { /** * Called when there is data ready on a ReadConn connection. * @param str the string read by the read thread, If null, the * connection closed or there was an error reading data */ public void dataReady(String str); }
A Simple Socket Client
Using these two classes, you can implement a simple client that connects to a server and uses a read thread to read the data returned by the server. The corresponding server for this client is presented in the next section, "The ServerSocket Class." Listing 34.3 shows the SimpleClient class.
Listing 34.3
Source Code for SimpleClient.java
import java.io.*; import java.net.*; /** * This class sets up a Socket connection to a server, spawns * a ReadThread object to read data coming back from the server, * and starts a thread that sends a string to the server every * 2 seconds. */ public class SimpleClient extends Object implements Runnable, ReadCallback { protected Socket serverSock; protected DataOutputStream outStream; protected Thread clientThread; protected ReadThread reader; public SimpleClient(String hostName, int portNumber) throws IOException { Socket serverSock = new Socket(hostName, portNumber); // The DataOutputStream has methods for sending different data types // in a machine-independent format. It is very useful for sending data // over a socket connection. outStream = new DataOutputStream(serverSock.getOutputStream()); // Create a reader thread reader = new ReadThread(this, serverSock); // Start the reader thread reader.start(); } // These are generic start and stop methods for a Runnable public void start() { clientThread = new Thread(this); clientThread.start(); } public void stop() { clientThread.stop(); clientThread = null; } // sendString sends a string to the server using writeUTF public synchronized void sendString(String str) throws IOException { System.out.println("Sending string: "+str); outStream.writeUTF(str); } // The run method for this object just sends a string to the server // and sleeps for 2 seconds before sending another string public void run() { while (true) { try { sendString("Hello There!"); Thread.sleep(2000); } catch (Exception oops) { // If there was an error, print info and disconnect oops.printStackTrace(); disconnect(); stop(); } } } // The disconnect method closes down the connection to the server public void disconnect() { try { reader.closeConnection(); } catch (Exception badClose) { // should be able to ignore } } // dataReady is the callback from the read thread. It is called // whenever a string is received from the server. public synchronized void dataReady(String str) { System.out.println("Got incoming string: "+str); } public static void main(String[] args) { try { /* Change localhost to the host you are running the server on. If it is on the same machine, you can leave it as localhost. */ SimpleClient client = new SimpleClient("localhost", 4331); client.start(); } catch (Exception cantStart) { System.out.println("Got error"); cantStart.printStackTrace(); } } }