其实,你只要看一个例子就可以明白了!

解决方案 »

  1.   

    其实,你只要看一个例子就可以明白了!
      

  2.   

    我是个初学者,哪有例子可以学学呢?
      

  3.   

    仅用一个类的TCP/IP服务器 作者:Greg Travis  来源:ZDNet   仅用一个类的服务器 
    作者: Greg Travis 
    日期: 2000年09月04日 
    <让我们通过一个Java程序的例子,学习建立一个简单的TCP/IP服务器。大部分代码都放在一个类中,这样就很容易入门-> 本文介绍了快速实现一个简单的TCP/IP服务器的技巧。核心代码都在单个类Server.java中,所以很容易建立和使用。 Server.java的结构很简单。它监听一个端口,对于每一个进来的连接,生成处理该连接的线程。实际处理该连接的子程序并没有实现,所以你必须自己扩展Server.java,写个子程序来实现。 (这样,从技术上讲,这就不是“仅用一个类的服务器”,因为你还需要用另外一个类,来完成某件事情。如果你真的坚持打算只用一个类,只需把子类中的代码放到Server.java中。) 下面的EchoServer.java的代码体现了该程序的简单性。EchoServer 完成如下的简单功能:把客户发来的信息再发回去。 ----------------------------------------------- 
    The One Class Server 
    ----------------------------------------------- 
    EchoServer.java 
    ----------------------------------------------- 
    ----------------------------------------------- 
    import java.io.*; 
    import java.io.*; public class EchoServer extends Server 

    // A single argument: the port on which to listen 
    public EchoServer( int port ) { 
    super( port ); 
    } // This function is called for each new connection; it 
    // implements whatever functionality is needed from the server. 
    // In this case, it simply sends back to the client all data 
    // that the client sends it. If it receives a 'q', the 
    // whole server is shut down. public void process( InputStream in, OutputStream out ) { 
    try { 
    while (true) { 
    int c = in.read(); 
    if (c=='q') { 
    close(); 
    } else { 
    out.write( c ); 


    } catch( IOException ie ) { System.out.println( ie ); } 
    } // Command-line: "java EchoServer <port>" 
    static public void main( String args[] ) throws Exception { 
    int port = new Integer( args[0] ).intValue(); 
    new EchoServer( port ); 


    Server类的实现是很有趣的,因为它对于所有线程使用了一个Server类的实例。 Listener 线程 
    创建的第一个线程是“listener”线程。该线程中的代码对一个端口进行监听,等待进入的连接。一旦一个连接进入时,一个新的“connection”线程被创建,用于处理该连接。 Listener线程必须把用某种方法把新连接的Socket对象传送给新线程。因为Java在创建线程时,不具有传递参数的功能,所以使用了另外一个技术:哈希表。 一个哈希表对象可以把线程对象映射为Socket对象。listener 线程创建了一个新的线程,然后把该新线程和新的socket放到哈希表中。当新线程开始执行时,它从哈希表基于自己的线程对象中,通过调用Thread.currentThread(),读入socket。 对于Listener线程来说,因为它不需要其他线程“传递”什么信息,此时的哈希表中就没有Socket对象,这样,程序就可以判断这是一个listener 线程而不是一个connection线程。 下面为Listener线程的代码。现在的这个实现很简单,因为它省略了一些处理。尤其是发生例外时的处理,我没有编写这些代码。因为这需要做更多的工作,而且依赖于具体的应用。 ----------------------------------------------- 
    The One Class Server 
    ----------------------------------------------- 
    The Listener Thread 
    ----------------------------------------------- 
    ----------------------------------------------- 
    import java.io.*; 
    import java.net.*; 
    import java.util.*; abstract public class Server implements Runnable 

    // The port the server will listen on 
    private int port; // Used to "pass" a Socket to the new thread that will process it private Hashtable handoff = new Hashtable(); // The first thread -- we store it here so we can kill it 
    // first when closing. private Thread listener; // A list of the Threads that have been started private Vector threads = new Vector(); 
    // A list of the Sockets that have connected to us private Vector sockets = new Vector(); // The listen socket 
    private ServerSocket ss; 
    public Server( int port ) { 
    this.port = port; 
    // Start the listener thread. Because we haven't passed a Socket 
    // object to this thread in the handoff table, it will know 
    // that it is to be the listener thread. 
    listener = new Thread( this ); 
    listener.start(); 

    synchronized public void close() { 
    // First, make sure there aren't any incoming connections 
    listener.stop(); // Now, close all the sockets 
    for (Enumeration e = sockets.elements(); e.hasMoreElements();){ 
    Socket s = (Socket)e.nextElement(); 
    try { 
    s.close(); 
    } catch( IOException ie ) { System.out.println( ie );} 
    } // And stop all the threads for (Enumeration e = threads.elements(); e.hasMoreElements();){ 
    Thread t = (Thread)e.nextElement(); // But let's not stop *ourselves* yet! 
    if (t != Thread.currentThread()) 
    t.stop(); 

    System.out.println( "Shutting down!" ); // Now we can stop ourselves. 
    Thread.currentThread().stop(); 
    } // This routine does the actual work of the server. It's not 
    // implemented, so you have to extend this class to actually get 
    // something done. abstract public void process( InputStream in, OutputStream out ); // This routine processes all the connections. All the threads 
    // started by this class run this same routine of the same instance 
    // of Server. public void run() { 
    // Get the Socket that is being "passed" to us by the listener 
    // thread. If there is no Socket here for us, then we ARE the 
    // listener thread, or at least we are about to be. Socket s = (Socket)handoff.get( Thread.currentThread() ); if (s==null) { 
    // Aha -- we are the very first thread, the listener thread. 
    // Start listening. 
    try { 
    // Set up the listen socket. 
    ss = new ServerSocket( port ); 
    System.out.println( "Listening on "+port ); while (true) { 
    // Accept a new connection 
    s = ss.accept(); 
    synchronized( this ) { 
    System.out.println( "Connection from "+s.getInetAddress() ); // Make a new thread to handle this connection 
    Thread t = new Thread( this ); // Store the thread and socket in the lists 
    sockets.addElement( s ); 
    threads.addElement( t ); // The Socket object is "passed" to the new thread by 
    // getting stuffed here. When the new thread is started, 
    // it will pull the Socket object out of here based on 
    // its own Thread object. handoff.put( t, s ); // All set! Start the thread! 
    t.start(); 


    } catch( IOException ie ) {} 
    } else { 
    // We are a processing socket. 
    try { 
    InputStream in = s.getInputStream(); 
    OutputStream out = s.getOutputStream(); 
    // Call the actually-do-something routine in the subclass of 
    // this object, so that something can actually get done. 
    process( in, out ); 
    } catch( IOException ie ) { System.out.println( ie ); } 


    } 此处,我们也没有对socket,线程列表以及对handoff哈希表进行整理,大家可以修改这个类,以便能够完善这些工作,我把它们的代码编写工作作为练习,留给读者。