Я сделал много поисков здесь, но я не нашел ничего, что хотя бы немного соответствовало тому, что мне нужно.
Я не очень разбираюсь в клиент-серверных приложениях, и это моя первая попытка, поэтому, пожалуйста, будьте терпеливы, если я допустил какую-то ошибку или задал глупые вопросы.
Теперь вернемся к моей проблеме..
Мне нужно создать многоклиентское/серверное приложение.
Серверная часть должна быть простым менеджером для клиентов.
Так, например:
- сервер может изменять некоторые параметры клиентов
- принимает файлы от клиентов
- другие скучные вещи.. которые в основном могут быть переведены в отправку строки или отправку файлов или получение строки и файлов
Клиенты, с другой стороны, представляют собой сложное приложение (по крайней мере, для пользователя), которое должно отправлять на сервер:
- некоторые регистрационные данные пользователя (здесь нет необходимости в безопасности, я уже довольно запутался с простым подключением клиент/сервер)
- PSD-файл, который должен быть результатом работы пользователя, поэтому, когда пользователь нажимает «Я готов», приложение получает этот PSD-файл и отправляет его на сервер для хранения.
- другая информация о клиенте, такая как данные конфигурации по умолчанию и т. д.
Итак, мой вопрос в основном таков: как я могу обрабатывать связь с сервера с одним конкретным клиентом? Я имею в виду, что у меня есть сервер, и я хочу изменить конфигурацию только для одного клиента.
Я предполагаю, что мне нужно каким-то образом хранить клиентов ... например, в массиве (List
), но я не знаю, правильный ли это способ сделать это. (В принципе, я не знаю, как работают классы Socket
и ServerSocket
.. если это поможет вам лучше понять)
Кроме того, когда сервер работает и слушает... графический интерфейс должен быть обновлен, чтобы отображать новых подключенных клиентов, поэтому мне нужен какой-то прослушиватель для сервера, который запускает действие обратно в интерфейс, когда появляется новый клиент? (Многие люди используют метод while(true) { socket = server.accept(); }, но мне это не кажется очень умным..)
Это основные файлы Client.java и Server.java, содержащие базовые функции клиента и сервера, которые я написал на основе большого количества поисковых запросов Google.
Но весь приведенный ниже код не соответствует всем моим потребностям.
Клиент.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;
}
}
эмм.. извините за мой английский.. пожалуйста.
server.accept()
, верно? Но даже если я сделаю что-то подобное, как мне обработать связь между сервером и конкретным клиентом? - person Andrea Rastelli   schedule 05.09.2013List
, в котором хранятся все эти объекты Thread, ведь у одного из них есть метод run(), который постоянно запрашивает что-то у соответствующего клиента .. верно? - person Andrea Rastelli   schedule 05.09.2013while (true) { accept(); /*...*/ }
. И в последнее время он снова стал более привлекательным с растущим использованием серверного JavaScript, в частности из-за Node.JS. Хорошая ли это идея... Ну, это зависит от того, что вы хотите сделать. - person haylem   schedule 05.09.2013Map<String, ClientThread>
. Итак, если мне нужно получить какую-то информацию о клиенте, я всегда могу получить к ней доступ по ключу карты, а если соединение прервется... Мне просто нужно перезаписать тот же ключ в карте, верно? - person Andrea Rastelli   schedule 05.09.2013