2013-07-14 264 views
2

我有一个Java程序将客户端连接到服务器。 这包括在客户端通过发送消息触发服务器后创建文件目录。例如:一旦服务器已经运行,客户端就会连接并发送msg,即“Your message:Lady”,服务器将收到一条消息,如“请求创建名为Directory的女士:Lady”,在此之后的目录将创建一个名为Lady。客户端 - 服务器连接

但问题是,这种连接是唯一一个对一个。就像只有一个客户端可以连接到服务器...

这是示例代码:

/* 
* To change this template, choose Tools | Templates 
* and open the template in the editor. 
*/ 
package today._; 

import java.io.*; 

import java.net.*; 

import java.text.*; 

import java.util.*; 

public class myServer { 

    protected static final int PORT_NUMBER = 55555; 

    public static void main(String args[]) { 

     try { 

      ServerSocket servsock = new ServerSocket(PORT_NUMBER); 

      System.out.println("Server running..."); 

      while (true) { 
       Socket sock = servsock.accept(); 
       System.out.println("Connection from: " + sock.getInetAddress()); 
       Scanner in = new Scanner(sock.getInputStream()); 
       PrintWriter out = new PrintWriter(sock.getOutputStream()); 
       String request = ""; 
       while (in.hasNext()) { 
        request = in.next(); 
        System.out.println("Request to Create Directory named: " + request); 

      if(request.toUpperCase().equals("TIME")) { 
        try { 
         File file = new File("C:\\" + request); 
         if (!file.exists()) { 
          if (file.mkdir()) { 
           System.out.println("Directory is created!"); 
          } else { 
           System.out.println("Failed to create directory!"); 
          } 
         } 
        } catch (Exception e) { 
         System.out.println(e); 
        } 
        out.println(getTime()); 

        out.flush(); 
      } else { 
       out.println("Invalid Request...");      
       out.flush(); 
      } 
       } 

      } 


     } catch (Exception e) { 
      System.out.println(e.toString()); 
     } 

    } 

    protected static String getTime() { 
     DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); 
     Date date = new Date(); 
     return (dateFormat.format(date)); 
    } 
} 

package today._; 

import java.io.*; 

import java.net.*; 

import java.util.*; 

public class myClient { 

     protected static final String HOST = "localhost"; 
     protected static final int PORT = 55555; 

     protected static Socket sock; 

     public static void main(String args[]) { 

     try { 

       sock = new Socket(HOST,PORT); 

       System.out.println("Connected to " + HOST + " on port " + PORT); 

       Scanner response = new Scanner(sock.getInputStream()); 
       PrintWriter request = new PrintWriter(sock.getOutputStream()); 
       BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); 
       String txt = ""; 

       while(!txt.toUpperCase().equals("EXIT")) { 

        System.out.print("Your message:"); 
        txt = in.readLine(); 

        request.println(txt); 
        request.flush(); 

        System.out.println(response.next()); 

       } 

       request.close(); 
       response.close(); 
       in.close(); 
       sock.close(); 

      } catch(IOException e) { 
       System.out.println(e.toString()); 
      } 
     } 

} 
+2

您需要每个客户端一个线程的服务器上。请参见本教程页的末尾:http://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html –

回答

2

多客户端的服务器一般都写的两种方法之一:

  1. 创建为每个客户端一个线程。为此,您可以创建一个线程来处理对服务器套接字上的accept()调用,然后生成一个新线程来处理它返回的套接字上的调用。如果你这样做,你需要确保你尽可能地隔离每个套接字的代码。接受线程将永远循环,或者直到设置了一个标志,并且只会调用accept,用新的套接字产生一个线程,然后返回到调用accept。所有的工作都在子线程中。

  2. 使用NIO,或其他技术,多路复用工作到1个更多的线程。 NIO使用一个有时称为select的概念,当有特定套接字的输入时,你的代码将被调用。

如果你只是在做一个小的服务器,你可以去用最简单的设计,也将不会有太多的客户,所以我会用#1去。如果你正在做一个大型的生产服务器,我会研究一下像netty或jetty这样的框架,它可以帮助你实现#2。 NIO可能会很棘手。

在这两种情况下,非常小心线程和文件系统,如果你不从并发包中使用一个锁,或同步或其他锁定方案你可能无法得到预期的结果。

我最后的忠告,要小心有客户告诉服务器做文件系统的任何东西。只是说,那就是做;-)

1

您的服务器类必须使用多线程来处理所有连接件危险的事:

class MyServer { 


    private ServerSocket servsock; 

    MyServer(){ 
     servsock = new ServerSocket(PORT_NUMBER); 
    } 

    public void waitForConnection(){ 
     while(true){ 
      Socket socket = servsock.accept(); 
      doService(socket); 
     } 
    } 

    private void doService(Socket socket){ 
     Thread t = new Thread(new Runnable(){ 
      public void run(){ 
       while(!socket.isClosed()){ 
        Scanner in = new Scanner(sock.getInputStream()); 
        PrintWriter out = new PrintWriter(sock.getOutputStream()); 
        String request = ""; 
        // and write your code 
       } 
      } 
     }); 
     t.start(); 
    } 
} 
+0

坏的做法,要创建一个新的'Scanner'和'PrintWriter'每个循环中,两个声明应该在循环之外。 – BackSlash

+0

是的。这是正确的。我无意中复制并粘贴user2565623代码中的这几行代码! :( – Vahid

+0

它仍然没有工作,有多个客户端可以在同一时间在一台服务器上连接..但是当第一个客户端退出连接时,另一个客户端将被连接。这就像先到先得服务方法..任何建议请:) – InformationTechnology