0

このあたりでたくさんの検索を行いましたが、必要なものに少しでも一致するものは見つかりませんでした。

私はクライアント/サーバー アプリケーションの専門家ではありません。また、これが初めての試みです。間違いを犯したり、ばかげた質問をしたりした場合は、しばらくお待ちください。

さて、私の問題に戻ります..

マルチクライアント/サーバー アプリケーションを構築する必要があります。

サーバー側は、クライアントの単純なマネージャーである必要があります。

たとえば、次のようになります。

  • サーバーは一部のクライアント パラメータを変更できます
  • クライアントからファイルを受け入れる
  • 他の退屈なもの..基本的に文字列の送信、ファイルの送信、または文字列とファイルの取得で翻訳できます

一方、クライアントは、サーバーに送信する必要がある (少なくともユーザーにとっては) 複雑なアプリケーションです。

  • いくつかのユーザー登録データ (ここではセキュリティの必要はありません。単純なクライアント/サーバー接続では既にかなり混乱しています)
  • ユーザー作業の結果である必要があるPSDファイル。ユーザーが「完了」をクリックすると、アプリケーションはこのPSDファイルを取得し、保存目的でサーバーに送信します
  • デフォルトの構成データなどの他のクライアント情報。

したがって、私の質問は基本的に次のとおりです。特定のクライアントとのサーバーからの通信をどのように処理できますか? つまり、私はサーバーを稼働させており、1 つのクライアントだけの構成を変更する必要があります。

クライアントを何らかの方法で保存する必要があると思います..配列( a List)のようですが、これが正しい方法であるかどうかはわかりません。Socket(基本的に、クラスと機能がどのように機能するかわかりServerSocketません..これが理解を深めるのに役立つ場合)

また、サーバーが起動してリッスンしているとき..新しい接続されたクライアントを表示するために GUI を更新する必要があるため、新しいクライアントが表示されたときにインターフェイスにアクションを返すサーバーへのある種のリスナーが必要ですか? (多くの人が while(true) { socket = server.accept(); } メソッドを使用していますが、これは私にはあまりスマートに聞こえません..)

これは、多くの Google 検索に基づいて作成したクライアントおよびサーバーの基本機能を含む基本的な Client.java および Server.java ファイルです。

しかし、以下のすべてのコードが私のすべてのニーズを満たしているわけではありません..

クライアント.java

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client extends Socket {

    private static Client    instance    = null;

    /**
     * The main init() function for this class, to create a Singleton instance for the Client
     * 
     * @param host
     *            The host of the Server
     * @param port
     *            The port of the Server
     * @return The Client instance that is a new instance if no one exists previusly,
     *         otherwise an older instance is returned
     * @throws UnknownHostException
     * @throws IOException
     */
    public static Client init( String host, Integer port ) throws UnknownHostException, IOException
    {
        if ( Client.instance == null )
            Client.instance = new Client( host, port );
        return Client.instance;
    }

    /**
     * Default Constructor made private so this class can only be instantiated by the
     * singleton init() function.
     * 
     * @param host
     *            The host of the server
     * @param port
     *            The port of the server
     * @throws UnknownHostException
     * @throws IOException
     */
    private Client( String host, Integer port ) throws UnknownHostException, IOException
    {
        super( host, port );
    }

    /**
     * Function used to send a file to the server.
     * When this function fires, the Client class start sending a file to the server.
     * Internally this function handles the filesize, and some other file information
     * that the server needs to store the file in the correct location
     * 
     * @param filename
     *            The filename of the file that will be sended to the server
     */
    public void sendFile( String filename ) throws FileNotFoundException, IOException
    {
        // The file object from the filename
        File file = new File( filename );

        // A string object to build an half of the message that will be sent to the exceptions
        StringBuilder exception_message = new StringBuilder();
        exception_message.append( "The File [" ).append( filename ).append( "] " );

        // Check if the file exists
        if ( !file.exists() )
            throw new FileNotFoundException( exception_message + "does not exists." );

        // Check if the file size is not empty
        if ( file.length() <= 0 )
            throw new IOException( exception_message + "has zero size." );

        // Save the filesize
        Long file_size = file.length();

        // Check if the filesize is something reasonable
        if ( file_size > Integer.MAX_VALUE )
            throw new IOException( exception_message + "is too big to be sent." );

        byte[] bytes = new byte[file_size.intValue()];

        FileInputStream fis = new FileInputStream( file );
        BufferedInputStream bis = new BufferedInputStream( fis );
        BufferedOutputStream bos = new BufferedOutputStream( this.getOutputStream() );

        int count;

        // Loop used to send the file in bytes group
        while ( ( count = bis.read( bytes ) ) > 0 )
        {
            bos.write( bytes, 0, count );
        }

        bos.flush();
        bos.close();
        fis.close();
        bis.close();
    }

    /**
     * Function used to send string message from client to the server
     * 
     * @param message
     *            The string message the server should get
     * @throws IOException
     */
    public void sendMessage( String message ) throws IOException
    {
        OutputStream os = this.getOutputStream();
        OutputStreamWriter osw = new OutputStreamWriter( os );
        BufferedWriter bw = new BufferedWriter( osw );

        bw.write( message );
        bw.flush();
    }

    /**
     * Function used to get a message from the Server
     * 
     * @return The message the server sent back
     * @throws IOException
     */
    public String getMessage() throws IOException
    {
        InputStream is = this.getInputStream();
        InputStreamReader isr = new InputStreamReader( is );
        BufferedReader br = new BufferedReader( isr );

        String message = br.readLine();

        return message;
    }
}

サーバー.java

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class Server extends ServerSocket {

    private static Server    instance    = null;
    private Socket            socket        = null;

    /**
     * 
     * @param port
     * @return
     * @throws IOException
     */
    public static Server init( Integer port ) throws IOException
    {
        if ( Server.instance == null )
            Server.instance = new Server( port );
        return Server.instance;
    }

    /**
     * 
     * @param port
     * @throws IOException
     */
    private Server( Integer port ) throws IOException
    {
        super( port );

        // Maybe this is something that needs to be improved
        while ( true )
            this.socket = this.accept();
    }

    /**
     * 
     * @param message
     * @throws IOException
     */
    public void sendMessage( String message ) throws IOException
    {
        OutputStream os = this.socket.getOutputStream();
        OutputStreamWriter osw = new OutputStreamWriter( os );
        BufferedWriter bw = new BufferedWriter( osw );

        bw.write( message );

        bw.flush();
    }

    /**
     * 
     * @return
     * @throws IOException
     */
    public String getMessage() throws IOException
    {
        InputStream is = this.socket.getInputStream();
        InputStreamReader isr = new InputStreamReader( is );
        BufferedReader br = new BufferedReader( isr );

        String message = br.readLine();

        return message;
    }
}

ええと..私の英語で申し訳ありません..お願いします。

4

2 に答える 2

2

あなたの質問は、現代のJavaアプローチがどのように見えるか、私を興味深くさせました。また、ソケットの実験を開始したときにいくつかの問題が発生したため、ここで役立つ小さな例を示します。

サーバーは、各クライアントを独自の「スレッド」で処理します。これは、基本的なクライアント/サーバー アーキテクチャであると言えます。しかしCallable<V>、スレッドの代わりに新しいものを使用しました。

私も拡張しSocketませんでしServerSocketた。私は前にそれを見ました。その場合、継承よりも構成を優先する方が良いと思います。何をどのように好むかを委任できるため、より詳細に制御できます。

詳細については、オラクルのチュートリアルをご覧になることをお勧めします。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ClientServerExample
{
  private final static int PORT = 1337;
  private final static String LOOPBACK = "127.0.0.1";

  public static void main(String[] args) throws IOException
  {
    ExecutorService se = Executors.newSingleThreadExecutor();
    se.submit(new Server(PORT, 5));

    ExecutorService ce = Executors.newFixedThreadPool(3);
    for (String name : Arrays.asList("Anton", "John", "Lisa", "Ben", "Sam", "Anne"))
      ce.submit(new Client(name, LOOPBACK, PORT));

    ce.shutdown(); while (!ce.isTerminated()) {/* wait */}
    se.shutdown();
  }
}

class Client implements Callable<Void>
{
  private final String name;
  private final String ip;
  private final int port;

  public Client(String name, String ip, int port)
  {
    this.name = name;
    this.ip = ip;
    this.port = port;
  }

  @Override
  public Void call() throws Exception
  {
    Socket s = new Socket(ip, port);
    PrintWriter out = new PrintWriter(s.getOutputStream(), true);
    out.println("Hi, I'm " + name + "!");
    out.close();
    s.close();
    return null;
  }
}

class Server implements Callable<Void>
{
  private final int port;
  private final int clients;
  private final ExecutorService e;

  public Server(int port, int clients)
  {
    this.port = port;
    this.clients = clients;
    this.e = Executors.newFixedThreadPool(clients);
  }

  @Override
  public Void call() throws Exception
  {
    ServerSocket ss = new ServerSocket(port);
    int client = 0;
    while (client < clients)
    {
      e.submit(new ClientHandler(client++, ss.accept()));
    }
    ss.close();
    e.shutdown(); while (!e.isTerminated()) {/* wait */}
    return null;
  }
}

class ClientHandler implements Callable<Void>
{

  private int client;
  private Socket s;

  public ClientHandler(int client, Socket s)
  {
    this.client = client;
    this.s = s;
  }

  @Override
  public Void call() throws Exception
  {
    BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
    String fromClient;
    while ((fromClient = in.readLine()) != null)
    {
      System.out.println("FROM CLIENT#" + client + ": " + fromClient);
    }
    in.close();
    s.close();
    return null;
  }
}

出力

クライアント#0 から: こんにちは、ジョンです。
クライアント#2 から: こんにちは、私はサムです!
クライアント#1 から: こんにちは、ベンです。
クライアント #3 から: こんにちは、アンです。
クライアント#4 から: こんにちは、私はアントンです!

于 2013-09-05T14:21:02.507 に答える