В вашем коде есть пара проблем.
- Основная проблема заключается в методе main класса Server.Ваш сервер принимает только одно соединение.Это соединение записывает и читает файл json, а затем ваш основной метод завершается.Если ваша основная программа заканчивается, то сервер исчез.Это означает, что первый клиент, который подключится, будет работать и записывать в файл, но любые последующие подключения не будут подключаться, потому что сервер больше не принимает подключения.Типичные серверы работают бесконечно, используя цикл while с
true
в качестве условия.
Пример Структура сервера без потоков:
public class Server {
// this class represents an instance of a client connection to this server
// It's an object that keeps track of the socket created by referencing
// the connection.
private class ClientInstanceOnTheServer {
private Socket connectionToClient;
public ClientInstanceOnTheServer(Socket connectionToClient) {
this.connectionToClient = connectionToClient;
}
private void logicToServeAClient() {
// here goes the logic that serves a client
}
public void run () {
try {
logicToServeAClient();
} finally {
try {
socket.close();
} catch (IOException e) {// handle exceptions!}
}
}
}
public static void main(String [] args) {
try {
ServerSocket serverSocket = new ServerSocket(1299);
while (true) { // run indefinitely
Socket socket = serverSocket.accept(); // accept connections from clients
// keep track of the socket object as it represents a connection to a client
// the server is responsible for keeping track of its connections to clients
// Example:
ClientInstanceOnTheServer client = new ClientInstanceOnTheServer(socket);
client.run();
}
} finally {
serverSocket.close();
}
}
}
Пример Структура сервера с потоками: ПРИМЕЧАНИЕ. Приведенный ниже код представляет собой не полное решение с потоками, а пример, объясняющий, как работает сервер.
public class Server {
// this class represents an instance of a client connection to this server
// It's an object that keeps track of the socket created by
// the connection and it runs in a separate thread to not block
// the main method thread on this server.
private class ClientInstanceOnTheServer extends Thread {
private Socket connectionToClient;
public ClientInstanceOnTheServer(Socket connectionToClient) {
this.connectionToClient = connectionToClient;
}
private void logicToServeAClient() {
// here goes the logic that serves a client
}
public void run () {
try {
logicToServeAClient();
} finally {
try {
socket.close();
} catch (IOException e) {// handle exceptions!}
}
}
}
public static void main(String [] args) {
try {
ServerSocket serverSocket = new ServerSocket(1299);
while (true) { // run indefinitely
Socket socket = serverSocket.accept(); // accept connections from clients
// keep track of the socket object as it represents a connection to a client
// the server is responsible for keeping track of its connections to clients
// and it should use a separate thread for each client to not block the main method thread.
// Example:
ClientInstanceOnTheServer client = new ClientInstanceOnTheServer(socket);
client.start(); // this will execute the run method in ClientInstanceOnTheServer class.
}
} finally {
serverSocket.close();
}
}
}
Ваш сервер всегда делает и пишет, и читает файл json, независимо от того, что хочет клиент.Сервер должен как-то позволить клиенту сообщать, что он хочет сделать, и тогда он выполняет только то, что просил клиент.Если мы будем использовать приведенный выше скелетный код, эта логика будет реализована в методе
logicToServeAClient
класса
ClientInstanceOnTheServer
.Сервер и клиент используют входные и выходные потоки объекта
socket
для связи друг с другом.Сервер и клиент должны заранее договориться о том, какие команды / операции нужны клиенту и сервер готов обслуживать.В вашем случае это будет
READ
и
WRITE
.Затем вы создаете контракт (протокол) между клиентом и сервером о том, как отправлять эти команды на сервер и как сервер будет отвечать клиенту для каждой команды.
Пример протокола:
// client sends READ to server
// client waits for respond from server
// server read json file and send it to the client
// client sends WRITE to server
// server then waits for the client to send the string to write.
// Once it receives the string, it writes it to the json file.
Все это достижимо при использовании потоков ввода и вывода сокета
Важно различать различия между классами Client
и ClientInstanceOnTheServer
.Клиент - это ваш класс Client
, который подключается к серверу, а ClientInstanceOnTheServer
хранит соединение, а также выполняет код сервера, который обслуживает команды, запрошенные классом Client
.В приведенном выше протоколе всякий раз, когда упоминается клиент, имеется в виду класс Client
.Всякий раз, когда упоминается, что сервер ссылается на класс ClientInstanceOnTheServer
.
В Google можно найти больше примеров, например: http://cs.lmu.edu/~ray/notes/javanetexamples/. Однако это должно помочь вам решить проблему.
Ура