Tải bản đầy đủ

Internet programming in java

Internet Programming in Java
( TCP Sockets)
Joseph Bergin
Pace University
jbergin@pace.edu

This is a short tutorial on internet programming in Java. It will show the basic techniques
used in servers and in clients. I will use an example adapted from Peter van der Linden's
Just Java (Prentice-Hall, 1998). A few years ago Peter Steiner had a cartoon in the New
Yorker. A dog was typing at a keyboard and talking to another dog over its shoulder. The
caption was: "On the internet, no one knows you're a dog." The running example here is
of a server that attempts to determine if its client is a dog.
The server begins an exchange by asking the client a question. The client responds. The
server then uses the response to determine if the client is a dog. The question is: "If you
met me, would you shake my hand or sniff it."
For internet programming in Java you have a number of alternatives. Here we will only
explore a middle level protocol called sockets. A TCP (tramission control protocol)
socket is a point to point two way communication stream on which the client and server
can exchange information of any type. We will just use strings. (A more sophisticated
mechanism in Java is RMI-Remote Method Invocation, in which the distinction between
client and server is erased and the two appear to be one application running over the net.)

Communication over sockets is exactly like reading to and writing from files. If a server
writes into a socket, the client can read it and conversely.
There are two kinds of sockets: server sockets and ordinary sockets. To establish a link, a
server must create a server socket on a port and then listen on that port by executing the
accept method. A port is a numbered logical connection point to the operating system.
Typically port numbers below 1024 are reserved for sytem use. For example port 80 is
usually the HTTP port and the FTP server usually listens on port 21. Only one server can
be installed on a given port.

The Server
Here is a simple dog server, adapted from Just Java. We will use port 4444, hoping that it
isn't currently in use on our server machine. If it is we will get an error when we run it


and will need to pick another port number. Clients will need to know this port number
also, as well as the IP address of the server or an equivalent domain name.
import java.io.*;
import java.net.*;
/**
* a network server that detects presence of dogs on the Internet
*
* @version
1.1 Jan 21 1996
* @author
Peter van der Linden
* @author
From the book "Just Java"
* Adapted by J. Bergin
*
*/
public class DogServer
{
public static void main(String a[]) throws IOException
{
int port = 4444;
Socket client = null;
// Next we create the server socket that we will listen to.
ServerSocket servsock = new ServerSocket(port);
it?";

String query = "If you met me would you shake my hand, or sniff

communication.

while (true)
{
// Wait for the next client connection
client = servsock.accept();
// Create the input and output streams for our

PrintStream out = new
PrintStream( client.getOutputStream() );
BufferedReader in = new BufferedReader(new
InputStreamReader( client.getInputStream()));
// Now you can just write to and read from these
streams.
// Send our query
out.println(query); out.flush();
// get the reply
String reply = in.readLine();
if (reply.indexOf("sniff") > -1)
{
System.out.println("On the Internet I
know this is a DOG!");

an AI experiment");
something.");

out.println("You're a dog.");
}
else
{

System.out.println("Probably a person or
out.println("You're a person or

}
out.flush();
// All done. Close this connection
client.close();


}

}

}

Once we have established the connection (when accept returns), the resulting socket will
give us its input and output streams which we can wrap in any convenient wrappers. Here
we used a PrintStream and a BufferedReader since all we want to write are strings. Note
that since this was intended as a demonstration, the server prints a trace of its results on
System.out. This isn't very realistic in a real server, however.
This program should be run in the background (and may need to be run by the system
administrator), so that it continues to run after you exit. On a UNIX system you would
run it with:
java DogServer &
On Windows95/98/NT you could run it in one DOS window, and run clients in another.
You could also use the start command.
This server will only handle one client at a time but it will queue up to 50 (the default)
clients waiting to connect. We will show how to do better below.

A Simple Client
Once you have a server, you need a client. Actually you can use a telnet program to
connect to port 4444 on the server and carry on the conversation directly. As soon as you
connect, the server will send you its question and await your answer. As soon as you
answer, it will send its reply and then break the connection. Note that a different server
could carry on a very long and involved transaction with the client. This is distinct from
what occurs with a CGI where the client initiates the conversation and the server
responds once and then always breaks the connection.
We will write a client in Java also, however. A very simple, text based client follows. This
illustrates only the simplest case of all.
Here we assume that the client runs on the same machine as the server. If not we need to
supply a URL or an IP address for the server machine.
// On the Internet no one knows you're a dog...
// unless you tell them.
import java.io.*;
import java.net.*;
class Dog
{
public static void main(String a[]) throws IOException
{
// Specify your server with a url or an IP address.


// if you try this on your system, insert your system

name
of loopback.

//

such as "sol.pace.edu" in the server string instead

String loopback = "127.0.0.1"; // "localhost" will also

work.

String server = loopback;
// Open our connection to the server, at port 4444
Socket sock = new Socket(server,4444);
// Get I/O streams from the socket
BufferedReader dis = new BufferedReader(new
InputStreamReader( sock.getInputStream() ));
PrintStream dat = new
PrintStream(sock.getOutputStream() );
// Now we can just read from and write to the streams.
// Start with reading for this server.
String fromServer = dis.readLine();
System.out.println("Got this from server: " +
fromServer);
String myReply = null;
BufferedReader in = new BufferedReader(new
InputStreamReader(System.in));
myReply = in.readLine();
dat.println(myReply);
fromServer = dis.readLine();
System.out.println("More from Server: "+ fromServer);

}

// All done. Close the connection.
sock.close();

}

A Threaded Server
Following is a more sophisticated server. It creates a new thread for each connection and
handles the transaction in that thread. The thread set up is fairly quick, so a waiting client
won't need to wait very long before it gets service, unlike the first version where a newly
arrived client would need to wait until the entire previous transaction completed.
import java.io.*;
import java.net.*;
/**
* A network server that detects presence of dogs on the Internet
*
This version of dogserver is multithreaded, spawning one new
thread for each client.
* @version
1.2 March 26 2000
* @author
Joseph Bergin
* @author
Adapted from the book "Just Java" by Peter van der Linden
* Adapted by J. Bergin


*
*/
public class ThreadedDogServer
{
public static void main(String a[]) throws IOException
{
int port = 4444;
Socket sock = null;
ServerSocket servsock = new ServerSocket(port);
while (true)
{
// wait for the next client connection
sock=servsock.accept();
// Create the new thread and hand it the socket.
Then start it.
}

new ClientHandler(sock).start();
}

private static class ClientHandler extends Thread
{
ClientHandler(Socket client)
{
this.client = client;
}
public void run()
{
// Get I/O streams from the client
try
{
PrintStream out = new
PrintStream( client.getOutputStream() );
BufferedReader in = new
BufferedReader(new InputStreamReader( client.getInputStream()));
String query = "If you met me would you
shake my hand, or sniff it?";
// Send our query
out.println(query); out.flush();
// get the reply
String reply = in.readLine();
if (reply.indexOf("sniff") > -1)
{
System.out.println("On the
Internet I know this is a DOG!");
out.println("You're a dog.");
}
else
{
System.out.println("Probably a
person or an AI experiment");
out.println("You're a person or
something.");
}
out.flush();
// Close this connection
client.close();
}
catch(IOException e)
{
System.out.println("Missed client.");
e.printStackTrace();
}


}
}

private Socket client = null;

}

Here we use an inner class to define the thread. It is static since we need to call its
constructor from a static method (main), but in general it need not be either static or
inner.
There are some problems with this design, however, in the case of a high volume server.
First, you wouldn't want to let the server create an unlimited number of threads. This
would make each run too slowly and the system would be unusable for all. Second, you
wouldn't want to wait for even the creation of the new threads, so you would modify this
so that old threads were saved (perhaps in a queue) for reuse by future clients. This server
also prints its trace to System.out, which is also unrealistic.

An Applet Client
Finally, here is an applet that can be used as a client. It isn't very sophisticated, but you
can see how the various key parts used above appear within applet code. Since the server
will disconnect after it makes a determination, we need to open a new socket each time
we want to get the question and answer it. In general any server establishes a protocol for
communication and the client will need to use this protocol.
Here the protocol is that the client connects, the server responds with a string and then
accepts a string. Finally the server responds to the client string with a string of its own
and then disconnects. The client may also disconnect in the middle of a transaction.
import
import
import
import
import

java.awt.*;
java.awt.event.*;
java.applet.*;
java.net.*;
java.io.*;

public class DogApplet extends Applet
{
public void init()
{
super.init();
setLayout(null);
resize(544,409);
answer = new Button("Answer Server");
AnswerListener answerlistener = new AnswerListener();
answer.addActionListener(answerlistener);
answer.setBounds(173,195,106,22);
add(answer);
reset = new Button("Reset");
reset.addActionListener(new ResetListener());
reset.setBounds(406,371,60,23);
add(reset);


label1 = new Label("From Server");
label1.setBounds(30,65,115,24);
add(label1);
label2 = new Label("Your Reply");
label2.setBounds(30,157,103,25);
add(label2);
label3 = new Label("Server's Judgement");
label3.setBounds(30,268,133,23);
add(label3);
label4 = new Label("Are you a dog? Answer the following
question.");

label4.setBounds(56,12,407,24);
add(label4);
fromServer = new TextField();
fromServer.setEditable(false);
fromServer.setBounds(172,67,343,36);
add(fromServer);
fromServer.setEnabled(false);
judgementFromServer = new TextField();
judgementFromServer.setEditable(false);
judgementFromServer.setBounds(172,261,343,36);
add(judgementFromServer);
judgementFromServer.setEnabled(false);
userReply = new TextField();
userReply.addActionListener(answerlistener);
userReply.setBounds(172,150,343,36);
add(userReply);
setVisible(true);

}

// Get the first question from the server.
firstQuestion();

void firstQuestion()
{
try
{
if(sock != null) sock.close();
getServerQuestion();
}
catch(IOException e)
{
fromServer.setText("Sorry, IO Error: " + e);
}
}
void getServerQuestion() throws IOException
{
sock = new Socket(host, port);
// Get I/O streams fromServer the socket
dis = new BufferedReader(new
InputStreamReader( sock.getInputStream() ));


dat = new PrintStream( sock.getOutputStream() );

}

e);

judgementFromServer.setText("");
String questionFromServer = dis.readLine();
fromServer.setText(questionFromServer);

private class AnswerListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String user = userReply.getText();
dat.println(user);
try
{
String judgement = dis.readLine();
fromServer.setText("");
judgementFromServer.setText(judgement);
sock.close();
}
catch(IOException exc)
{
fromServer.setText("Sorry, IO Error: " +
}
sock = null;
}

}

private class ResetListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
try
{
if(sock == null){ getServerQuestion();}
}
catch(IOException exc)
{
fromServer.setText("Sorry, IO Error: " +
e);

}
}

}

private class WindowCloser extends WindowAdapter
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
}
private String host = "localhost";
private int port = 4444;
private
private
private
private
private
private
private
private
private

Button answer;
Button reset;
Label label1;
Label label2;
Label label3;
Label label4;
TextField fromServer;
TextField judgementFromServer;
TextField userReply;

private Socket sock = null;


private BufferedReader dis;
private PrintStream dat;
}

A Chat Server and Client
Somewhat more sophisticated is a Chat server and client. This is also quite simple but
shows what you need to do when the threads in your server need to interact. In this case
they need to communicate with each other so that the text typed by one user can be sent
to all the users. This example uses a shared buffer for this.

Note. The book Just Java from which this was developed has nice chapters on network
programming and on graphical programming, especially the concept of smooth animation
using double buffering. Other books in the same series are also excellent for examples of
Java techniques.
Last Updated: March 27, 2000



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay

×

×