| Blog信息 |
|
blog名称: 日志总数:1304 评论数量:2242 留言数量:5 访问次数:7706052 建立时间:2006年5月29日 |

| |
|
[J2SE]Writing a multithreaded Socket Server 软件技术
lhwork 发表于 2006/8/7 10:31:24 |
| This example demonstrates the creation of a multithreaded socket
server application. The server is currently a simple Echo Server,
which simply accepts what the client says and sends it back. The
example demonstrates the basic infrastructure for a true
multithreaded server application and can be directly enhanced to
perform as any server application.
The EchoServer accepts multiple client connections and is capable
of serving them simultaneously. It uses a new thread to service every
new client, which allows it to accepts new clients even before all
clients are serviced. The server also identifies each client
connection with a unique ID, making it easy to identify clients if
required.
The EchoServer only understands one command, “quit”.
On receiving this command, it quits the thread servicing the client
and closes the connections. Also worth noting are the various places
where a network connection could fail. All conditions are handled
gracefully by EchoServer, thus making sure that the server never
leaves behind residual threads and that the client is not capable of
crashing the server.
Example Code:
About the Author
Anand is a Senior Software Engineer at Symantec
Corporation. He has a Masters degree in Computer Science from
University of Pune, India. Anand started his career as a C++
programmer, shifting focus to Java. He is a server side buff, and
believes Server-side Java is it. Over the years, Anand has designed and
implemented numerous projects in Java, C++ and Visual Basic. Primary interests are networking and server side technologies, primarily J2EE.
Anand is also interested in teaching and uses his spare time to teach
Java. He can be reached at anandh (at) javareference (dot) com
More examples by Anand Hariharan 500)this.width=500'>
Advertisement
EchoServer.java : The Server application
import java.net.*;
import java.io.*;
public class EchoServer
{
ServerSocket m_ServerSocket;
public EchoServer()
{
try
{
// Create the server socket.
m_ServerSocket = new ServerSocket(12111);
}
catch(IOException ioe)
{
System.out.println("Could not create server socket at 12111. Quitting.");
System.exit(-1);
}
System.out.println("Listening for clients on 12111...");
// Successfully created Server Socket. Now wait for connections.
int id = 0;
while(true)
{
try
{
// Accept incoming connections.
Socket clientSocket = m_ServerSocket.accept();
// accept() will block until a client connects to the server.
// If execution reaches this point, then it means that a client
// socket has been accepted.
// For each client, we will start a service thread to
// service the client requests. This is to demonstrate a
// multithreaded server, although not required for such a
// trivial application. Starting a thread also lets our
// EchoServer accept multiple connections simultaneously.
// Start a service thread
ClientServiceThread cliThread = new ClientServiceThread(clientSocket, id++);
cliThread.start();
}
catch(IOException ioe)
{
System.out.println("Exception encountered on accept. Ignoring. Stack Trace :");
ioe.printStackTrace();
}
}
}
public static void main (String[] args)
{
new EchoServer();
}
class ClientServiceThread extends Thread
{
Socket m_clientSocket;
int m_clientID = -1;
boolean m_bRunThread = true;
ClientServiceThread(Socket s, int clientID)
{
m_clientSocket = s;
m_clientID = clientID;
}
public void run()
{
// Obtain the input stream and the output stream for the socket
// A good practice is to encapsulate them with a BufferedReader
// and a PrintWriter as shown below.
BufferedReader in = null;
PrintWriter out = null;
// Print out details of this connection
System.out.println("Accepted Client : ID - " + m_clientID + " : Address - " +
m_clientSocket.getInetAddress().getHostName());
try
{
in = new BufferedReader(new InputStreamReader(m_clientSocket.getInputStream()));
out = new PrintWriter(new OutputStreamWriter(m_clientSocket.getOutputStream()));
// At this point, we can read for input and reply with appropriate output.
// Run in a loop until m_bRunThread is set to false
while(m_bRunThread)
{
// read incoming stream
String clientCommand = in.readLine();
System.out.println("Client Says :" + clientCommand);
if(clientCommand.equalsIgnoreCase("quit"))
{
// Special command. Quit this thread
m_bRunThread = false;
System.out.print("Stopping client thread for client : " + m_clientID);
}
else
{
// Echo it back to the client.
out.println(clientCommand);
out.flush();
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
// Clean up
try
{
in.close();
out.close();
m_clientSocket.close();
System.out.println("...Stopped");
}
catch(IOException ioe)
{
ioe.printStackTrace();
}
}
}
}
}
EchoClient.java : The client application
import java.net.*;
import java.io.*;
// A client for our multithreaded EchoServer.
public class EchoClient
{
public static void main(String[] args)
{
// First parameter has to be machine name
if(args.length == 0)
{
System.out.println("Usage : EchoClient <serverName>");
return;
}
Socket s = null;
// Create the socket connection to the EchoServer.
try
{
s = new Socket(args[0], 12111);
}
catch(UnknownHostException uhe)
{
// Host unreachable
System.out.println("Unknown Host :" + args[0]);
s = null;
}
catch(IOException ioe)
{
// Cannot connect to port on given host
System.out.println("Cant connect to server at 12111. Make sure it is running.");
s = null;
}
if(s == null)
System.exit(-1);
BufferedReader in = null;
PrintWriter out = null;
try
{
// Create the streams to send and receive information
in = new BufferedReader(new InputStreamReader(s.getInputStream()));
out = new PrintWriter(new OutputStreamWriter(s.getOutputStream()));
// Since this is the client, we will initiate the talking.
// Send a string.
out.println("Hello");
out.flush();
// receive the reply.
System.out.println("Server Says : " + in.readLine());
// Send a string.
out.println("This");
out.flush();
// receive a reply.
System.out.println("Server Says : " + in.readLine());
// Send a string.
out.println("is");
out.flush();
// receive a reply.
System.out.println("Server Says : " + in.readLine());
// Send a string.
out.println("a");
out.flush();
// receive a reply.
System.out.println("Server Says : " + in.readLine());
// Send a string.
out.println("Test");
out.flush();
// receive a reply.
System.out.println("Server Says : " + in.readLine());
// Send the special string to tell server to quit.
out.println("Quit");
out.flush();
}
catch(IOException ioe)
{
System.out.println("Exception during communication. Server probably closed connection.");
}
finally
{
try
{
// Close the streams
out.close();
in.close();
// Close the socket before quitting
s.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
}
Demonstration:
To run the server, compile the source and run it by typing "java EchoServer" on the command prompt.
>java EchoServer
Listening for clients on 12111...
The server indicates that it is listening for connections. To run the
client, simply run java EchoClient localhost (if running on the same
machine), substitute "localhost" with the machine name the server is
running on, if over a network.
>java EchoClient localhost
Server Says : Hello
Server Says : This
Server Says : is
Server Says : a
Server Says : Test
On running the client, the above output will be displayed at the client side, and the following output, on the server side.
Accepted Client : ID - 0 : Address - 127.0.0.1
Client Says :Hello
Client Says :This
Client Says :is
Client Says :a
Client Says :Test
Client Says :Quit
Stopping client thread for client : 0...Stopped
|
|
|