Рейтинг:
20
Arthur V. Ratz
Вот мое решение:
*Редактировать* ClientApp.java:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package clientapp;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author Arthur V. Ratz
*/
public class ClientApp {
// Declare an asynchronous thread class
public static class QueueClientThread extends Thread {
private BufferedReader m_in;
// Pass the buffered reader object to the constructor
public QueueClientThread(BufferedReader in) {
m_in = in;
}
public void run() {
// Run into an endless eternal loop to enforce receiving messages
// from the multi-threaded server in real-time mode
while (true) {
try {
String msg_buf = "\0";
// Fetch each incoming response data received from multi-
// threaded server, forwarded back from single-threaded
// server at the back-end
while ((msg_buf = m_in.readLine()) != null) {
// Print out the response message received
System.out.println("Greetings from singlethreaded server: " + msg_buf);
}
// Assert on the IO exception
} catch (IOException ex) {
// Log the specific IO exception
Logger.getLogger(ClientApp.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// Set multithreaded server hostname
String hostName = "127.0.0.1";
// Set multithreaded server port number
int portNumber = Integer.parseInt("5056");
try {
// Instantinate client's socket object
Socket clientSocket = new Socket(hostName, portNumber);
// Instantinate print writer object to send requests to
// multi-threaded server
PrintWriter outputStream = new PrintWriter(
clientSocket.getOutputStream(), true);
TimerTask clientTask;
// Create a timer task object
clientTask = new TimerTask() {
// Implement run() method that will send a message
// to multi-threaded server via a client socket created
public void run() {
// Print out message
System.out.println("Sending a message...");
// Send a message with randomly generated msg_id to
// multi-threaded server
outputStream.println("msg_id: " + Integer.toString(
new Random().nextInt(1000) + 1));
try {
// Launch the asynchronous thread to receive the
// responses from multithreaded server, forwarded by
// single-threaded server at the back-end
new QueueClientThread(new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()))).start();
// Assert on the IO exception
} catch (IOException ex) {
// Log the error
Logger.getLogger(ClientApp.class.getName()).log(Level.SEVERE, null, ex);
}
}
};
// Execute a timer-task each 1000 ms to send out a message to
// multi-threaded server.
new Timer().schedule(clientTask, 200L, 1000L);
// Assert on the IO exception
} catch (IOException ex) {
// Log the IO exception if socket opened fails
Logger.getLogger(ClientApp.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
*Редактировать* MTServer.java:/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package mtserver;
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.ArrayList;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author Arthur V. Ratz
*/
public class MTServer {
// Declaring the asynchronous thread class
public static class QueueClientThread extends Thread {
private BufferedReader m_in;
private PrintWriter m_out;
// Passing the buffered reader and print writer objects to the constructor
public QueueClientThread(BufferedReader in, PrintWriter out) {
m_in = in; m_out = out;
}
public void run() {
// Enter an endless eternal while-loop to enforce multithreaded-
// server incoming socket to receive incoming data from single-threaded
// server in real-time mode.
while (true) {
try {
String msg_buf = "\0";
// Retrieving messages from each client by calling
// buffered reader's readLine(…) method
while ((msg_buf = m_in.readLine()) != null) {
// For each message redirect it back to specific client, from
// which a client socket was accepted and connection
// established
System.out.println("Message sent back to client: " + msg_buf);
m_out.println("Message sent back to client: " + msg_buf);
}
// Assert on IO exception
} catch (IOException ex) {
// Log the error
Logger.getLogger(MTServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
// Declaring the asynchronous thread class
public static class QueueMTServerThread extends Thread {
private Socket m_Socket;
// Passing the client socket object the constructor
public QueueMTServerThread(Socket socket) {
m_Socket = socket;
}
public void run() {
try (
// Instantinate printer writer object to send data to single threaded
// server
PrintWriter out =
new PrintWriter(m_Socket.getOutputStream(), true);
// Instantinate the buffered reader to fetch the requests data
// sent to multithreaded server by one or more clients
BufferedReader in = new BufferedReader(
new InputStreamReader(m_Socket.getInputStream()));
) {
String inputLine;
// Fetching data sent by each client by calling buffered reader's
// readLine(…) method and forward the data to single threaded server
while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
//out.println(inputLine);
// Setting the hostname of single-threaded server
String hostName = "127.0.0.1";
// Setting the port number of the single-threaded server
int portNumber = Integer.parseInt("5058");
// Creating a client socket object to establish connection
// to single-threaded server
Socket clientSocket = new Socket(hostName, portNumber);
// Instantinating the printer writer object to send
// data to single-threaded server
PrintWriter outputStream = new PrintWriter(
clientSocket.getOutputStream(), true);
// Forward current incoming message to single-threaded server
outputStream.println(inputLine);
// Launch the asynchronous thread to receive data back
// from single-threaded server
new QueueClientThread(new BufferedReader(
new InputStreamReader(clientSocket.getInputStream())), out).start();
}
// Assert on the IO exception
} catch (IOException e) {
// Print out exception message
System.out.println(e.getMessage());
}
}
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws IOException {
// Assign the tcp protocol port number
int portNumber = Integer.parseInt("5056");
try {
// Instantinate server socket object to listen tcp port 5056
ServerSocket serverSocket = new ServerSocket(
Integer.parseInt("5056"));
// Entering the endless eternal while-loop during the execution
// of which we accept a client socket for each client's connection
// making it possible to accept and data sent by one
FerdouZ
Привет Артур,
Когда я запускаю этот проект, он выполняется непрерывно.Могу ли я сделать этот проект похожим на =>
сообщение может быть отправлено от клиента, и он ответит от STserver. Код довольно запутанный, вот почему я не могу понять его правильно.
Спасибо
Arthur V. Ratz
Привет, Фердуз. Я добавил конкретные комментарии к коду, чтобы вы могли понять его правильно. Кроме того, я дал объяснение основной идеи этого решения. Пожалуйста, прочтите и оставьте свой комментарий, если вы можете понять решение прямо сейчас.
FerdouZ
Привет, Артур, Спасибо за добавление комментария в код. на самом деле я хочу именно так
"Однако правильное протокольное решение заключается в том, что каждый клиент отправляет сообщение запроса на многопоточный сервер, который немедленно пересылает входящие запросы на однопоточный сервер, который, в свою очередь, отправляет дату ответа обратно на многопоточный сервер, а затем пересылает его обратно конкретному клиенту. Это правильное и наиболее подходящее решение этой проблемы."
Могу ли я отправить сообщение/данные вручную от клиентов, и он автоматически ответит с сервера?
Спасибо
Arthur V. Ratz
- Да, можешь. Я использовал таймер только для демонстрационных целей. Нужен модифицированный код ? Я переработаю код клиентского приложения и опубликую его в качестве решения.
Arthur V. Ratz
Фердуз, теперь вы можете использовать код для отправки сообщений запроса без таймера, так что вы можете отправлять сообщения/данные вручную от клиентов, и он будет автоматически отвечать с сервера...
FerdouZ
Большое спасибо, Артур, за помощь.
На самом деле, к сожалению, он автоматически завершается после отправки одного значения. могу ли я сделать это способным отправлять несколько значений от клиентов, и это будет прекращено после отправки "выхода" или любого конкретного значения?
Спасибо.
Arthur V. Ratz
Отправка нескольких значений от каждого клиента по ТИКам таймера уже была реализована. Если вы хотите изменить поведение этого приложения с помощью своего собственного, пожалуйста, скажите мне, что должно делать ваше клиентское приложение, и я постараюсь вам помочь.
FerdouZ
Клиентское приложение может отправлять данные вручную несколько раз,и оно будет прекращено после отправки одного конкретного значения, такого как Exit, Over и т. д..
Пример:один клиент отправляет одни данные, а затем автоматически получает ответ от сервера.тогда один и тот же клиент может снова отправлять разные данные и так далее ... тогда клиент может прервать соединение, когда захочет.
Arthur V. Ratz
Означает ли это на самом деле, что клиентское приложение должно получать пользовательский ввод ? Если да, то я скоро опубликую обновление.
FerdouZ
да, это нужно для получения пользовательского ввода, но мне нужно принимать ввод несколько раз от одного и того же клиента.
Спасибо
FerdouZ
Еще одна вещь, сэр, здесь STserver принимает несколько соединений, но я хочу только одно соединение.
Arthur V. Ratz
STserver в этом случае поддерживает только одно соединение с MTServer
Arthur V. Ratz
Пожалуйста, наконец, дайте мне знать, были ли все эти вещи, которые я разместил в качестве решения, полезны или нет.
Arthur V. Ratz
Это только для моего интереса. :)
Arthur V. Ratz
Просто для вашего интереса, на эту тему стоит написать статью. Я имею в виду вопросы, связанные с Java-сокетами.
FerdouZ
Благодарю вас, сэр, это прекрасно работает.Теперь я понимаю.
Еще раз спасибо за помощь . :)
Arthur V. Ratz
Всегда пожалуйста, сэр.
Arthur V. Ratz
Вот ваше решение, получающее пользовательский ввод, опубликованное выше.
FerdouZ
Если STserver отключен на некоторое время, то запустите его снова, после чего можно получить автоматическое соединение с MTserver, с которым сервер соединялся ранее.Если возможно,можете помочь мне, как это сделать, сэр?
Arthur V. Ratz
- Нет проблем, сэр. Я помогу тебе выбраться. Я опубликую свой улучшенный код чуть позже. В настоящее время я работаю над этим.
FerdouZ
Окей сэр, благодарю вас.
Arthur V. Ratz
Фердуз, я опубликовал свое обновление решения в качестве решения 2 для вашего вопроса. Скачайте файл по ссылке ниже и скажите мне, работает ли он для вас или нет.
Arthur V. Ratz
Фердуз, у меня есть готовое решение. Можете ли вы пересмотреть решение ?
FerdouZ
Извините, сэр, за поздний ответ. Эта ссылка не работает.можете ли вы проверить?