[英]Java - Using sockets to read from and write to files, by different methods
我基本上有一個應用程序,可以讓客戶預訂電影院的電影。 它還具有可以控制用戶數據庫的管理員和負責電影和收看數據庫的內容管理員。
此時,我們不需要使用實際的數據庫,而是可以讀寫文件。 我們必須通過套接字來做到這一點。 文件位於服務器上,客戶端通過套接字之間的連接獲取或發送數據。
管理員,內容管理員和用戶使用不同的Java文件,每個文件包含每個用戶類使用的方法。 所有這些Java文件都在客戶端。
我有以下問題。
程序的所有“邏輯”(包含方法的.java文件)都在客戶端是否正確?
我必須在服務器端使用一個插槽,在客戶端使用一個插槽嗎? 在這種情況下,來自不同java文件的所有方法都通過一個客戶端套接字進行通信並傳遞數據。
不同的方法讀取和寫入不同的文件。 我如何告訴從客戶端到服務器通過套接字的數據需要寫入特定文件? (從適當的文件讀取相同)
還有兩個更具體的示例。
a)有一種方法可以讓管理員將用戶添加到Users.txt文件中。 管理員通過main方法將userId(用於區分管理員,內容管理員和用戶),名稱,用戶名和密碼作為addUser()方法的參數。 如何通過套接字發送數據並將其寫入正確的文件? 服務器端是否存在一個具有將數據寫入文件的寫入器的對應方法? 此外,我是否全部以一行或不同部分的形式發送數據?
public void createUser(int userId, String name, String username, String password){
try{
PrintWriter Writer = new PrintWriter(new BufferedWriter(new FileWriter("Users.txt", true)));
boolean appendToFile = true;
if (appendToFile) {
Writer.println(userId + " " + name + " " + username + " " + password);
}
System.out.println("The user "+getUsername()+" was created!");
Writer.close();
}
catch (IOException e) {
}
}
b)另一種方法使客戶能夠基於關鍵字搜索電影。 我們需要搜索Films.txt文件的每一行(其結構為filmId(int); filmCategory(enum); filmTitle(string); filmDesription;)。 searchViewings()方法通過套接字發送用戶提供的關鍵字,在服務器端,它需要在文件的每一行中搜索電影標題中的關鍵字。 再有,是否有一個containsind方法包含用於搜索文件每一行的邏輯? 否則,只有關鍵字可用的服務器端如何知道如何處理呢?
public void searchViewings(String keyword){
File inputFile = new File("Provoles.txt");
String currentLine = null;
boolean flag = false;
try{
BufferedReader Reader = new BufferedReader(new FileReader(inputFile));
System.out.println("The movies that contain the keyword '"+keyword+"' have the following available viewings:");
while ((currentLine = Reader.readLine()) != null) {
String s = currentLine;
String delims = ";";
String[] tokens = s.split(delims);
if (tokens[1].indexOf(keyword) != -1){
flag = true;
System.out.println("The movie with Film ID '"+tokens[0]+"' and Film Title '"+tokens[1]+"' has an available viewing at the cinema with ID '"+tokens[2]+"'.");
}
}
if (flag == false){
System.out.println("There is no movie containing the current keyword.");
}
Reader.close();
}
catch (IOException e) {
}
}
上面的代碼在實現任何套接字之前都是這樣的。
程序的所有“邏輯”(包含方法的.java文件)都在客戶端是否正確?
並非沒有必要在服務器端也使用Java或其他語言編寫某種邏輯。 否則,服務器將無法讀取文件,執行邏輯或將文件發送給客戶端。
我必須在服務器端使用一個插槽,在客戶端使用一個插槽嗎? 在這種情況下,來自不同java文件的所有方法都通過一個客戶端套接字進行通信並傳遞數據。
您不必這樣做,因此您當然需要至少一個插槽,但也可以使用多個插槽。 例如,管理員使用的套接字和客戶端使用的套接字。
不同的方法讀取和寫入不同的文件。 我如何告訴從客戶端到服務器通過套接字的數據需要寫入特定文件? (從適當的文件讀取相同)
您可以通過套接字發送標頭,例如:read / file1或write / file4。 或類似的事情,關鍵是發送一些數據告訴服務器該怎么做。
最后,有沒有使用多個我可以讀取或運行的文件的示例?
目前我還沒有,但是我會用Google搜索一下,如果以后找到它,請稍后進行更新。
我希望這有幫助 :)
要回答第一個問題,您可以將應用程序邏輯存儲在客戶端(又名胖/胖客戶端)或服務器(瘦客戶端)上。 據我所知,沒有一個確切的答案是“更好”。 這確實取決於您的應用程序。 如果您希望大多數處理由服務器完成,則使用瘦客戶機(存儲在服務器上的邏輯)(這對於處理能力有限的設備(例如智能手機)而言是理想的)。 如果您希望在客戶端上執行更多處理,或者訪問服務器的帶寬有限,請使用胖客戶端。 關於胖與瘦客戶機的文章很多。 這是您可能會發現有用的一種 。
我對套接字有點生疏,所以您可能想采納其他答案的建議,但據我所知,每個客戶端將具有1+套接字,而服務器也將具有1+(取決於您選擇的方式)。實現您的連接)套接字。 客戶端和服務器將使用相同的端口號。 請參見本文章對於一些簡單的例子。 當我嘗試它們時,我將ServerSocket用於服務器,將Socket用於客戶端。 在上面的鏈接中查看不同的示例以獲取想法。 如果您還有其他問題,請告訴我們,我們將盡力詳細說明。
這是一個簡單的項目,使用套接字和文件讀取和寫入我之前做過的事情。 希望查看此代碼將闡明您對自己的代碼的疑問。 由於時間限制,我沒有將其轉換為包括您提供的代碼段,但是如果您在看完我的代碼后仍然堅持使用自己的代碼,我將為您提供幫助。
如果運行此代碼,請注意以下幾點:
服務器代碼
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class FileServer extends JFrame {
//main function
public static void main(String[] args) {
int port = Integer.parseInt(args[0]);
//String file = args[1];
FileServer server = new FileServer(port);
server.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
server.runServer();
}
//FileServer class declarations
private File file; //for this example, the file is stored in the root project directory and includes the file extension (ie: .txt, etc)
private ServerSocket ss;
private Socket connection;
private JTextField field;
private JTextArea displayArea;
private int portNum;
private ObjectOutputStream oos;
private ObjectInputStream ois;
public FileServer(int port) {
super("Server");
//file = new File(f); //sent from client or done here?
portNum = port;
field = new JTextField();
field.setEditable(false);
field.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent event) {
sendData(event.getActionCommand());
field.setText("");
}
}); //ends addActionListener
add(field, BorderLayout.NORTH);
displayArea = new JTextArea();
add(new JScrollPane(displayArea));
setSize(500, 300);//size of JFrame
setVisible(true);
}//end constructor
/**
* code that executes the server obj. Think of it as FileServer's main(). This is called from main().
*/
public void runServer() {
try {
ss = new ServerSocket(portNum, 100); //creates server socket with port # specified by user and a queue of 100
while (true) { //infinite loop to continually listen for client connections
try {
waitForConnection(); //wait for client connections
getStreams(); //get I/O streams
processConnection();
}
catch (EOFException e) {
e.printStackTrace();
}
finally {
closeConnection();
}
}
}
catch (IOException e) {
e.printStackTrace();
}
}//end runServer
/**
* creates socket obj to interact with client. Socket created when connection with client made
* @throws IOException
*/
public void waitForConnection() throws IOException {
displayMessage("Waiting for connection\n");
connection = ss.accept(); //returns socket obj when connection made with client
displayMessage("Connection made with " + connection.getInetAddress().getHostName());
}//end waitForConnection
/**
* gets IO stream objs for FileServer class
*/
public void getStreams() {
try {
oos = new ObjectOutputStream(connection.getOutputStream());
oos.flush();
ois = new ObjectInputStream(connection.getInputStream());
}
catch (IOException e) {
e.printStackTrace();
}
displayMessage("\n Got both IO streams \n");
}//end getStreams
/**
* receives filename sent from client and creates file
*/
public void processConnection() throws IOException {
sendData("Connection successful");
setTextFieldEditable(true);
do { //added do while for testing
try {
String message = (String) ois.readObject(); //should read in filename then create file obj
displayMessage("\n " + message + " received from client\n");
displayMessage("Type in absolute path of file in text field above");
file = new File(message);
if(!file.exists()) {
sendData("File not found");
}
else {
Scanner cin = new Scanner(file);
while(cin.hasNextLine()) {
message = cin.nextLine();
sendData(message);
}
cin.close();
}
}
catch (ClassNotFoundException e) {
e.printStackTrace();
}
} while(true);
}//end processConnection
/**
* closes IO streams
*/
public void closeConnection() throws IOException {
displayMessage("\nClosing connections\n");
setTextFieldEditable(false);
oos.close();
ois.close();
connection.close();
}//end closeConnection
/**
* sends message to client
* @param message
*/
public void sendData(String message) {
try{
oos.writeObject(message);//this is what sends message
oos.flush();
displayMessage("\n in sendData: " + message + "\n");
}
catch(IOException e) {
displayArea.append("\n Error writing object");
e.printStackTrace();
}
}//end sendData
public void displayMessage(final String message) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
displayArea.append(message);
}
});//end SwingUtilties
}
private void setTextFieldEditable( final boolean editable )
{
SwingUtilities.invokeLater(
new Runnable()
{
public void run() // sets enterField's editability
{
field.setEditable( editable );
} // end method run
} // end anonymous inner class
); // end call to SwingUtilities.invokeLater
} // end method setTextFieldEditable
}
客戶代碼
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class FileClient extends JFrame
{
public static void main(String[] args) {
int port = Integer.parseInt(args[0]);
String fileName = args[1]; //must use absolute path for filename
FileClient app = new FileClient("127.0.0.1", port, fileName);
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.runClient();
}
private JTextField enterField; // enters information from user
private JTextArea displayArea; // display information to user
private ObjectOutputStream output; // output stream to server
private ObjectInputStream input; // input stream from server
private String message = ""; // message from server
private String chatServer; // host server for this application
private Socket client; // socket to communicate with server
private int portNum;
private String fileName;
private File file;
// initialize chatServer and set up GUI
public FileClient( String host, int port, String fileName )
{
super( "Client" );
portNum = port;
this.fileName = fileName;
//file = new File(fileName);
chatServer = host; // set server to which this client connectsS
enterField = new JTextField(); // create enterField
enterField.setEditable( false );
enterField.addActionListener( //need to find a way to send fileName to server without having to type it in
new ActionListener()
{
// send message to server
public void actionPerformed( ActionEvent event )
{
sendData( event.getActionCommand() );
enterField.setText( "Messages will be displayed in other text box" );
} // end method actionPerformed
} // end anonymous inner class
); // end call to addActionListener
add( enterField, BorderLayout.NORTH );
displayArea = new JTextArea(); // create displayArea
add( new JScrollPane( displayArea ), BorderLayout.CENTER );
setSize( 500, 300 ); // set size of window
setVisible( true ); // show window
} // end Client constructor
// connect to server and process messages from server
public void runClient()
{
try // connect to server, get streams, process connection
{
connectToServer(); // create a Socket to make connection
getStreams(); // get the input and output streams
processConnection(); // process connection
sendData(fileName); //sends name of file to server to retrieve
displayMessage("Sent request for " + fileName + " to server.");
} // end try
catch ( EOFException eofException )
{
displayMessage( "\nClient terminated connection" );
} // end catch
catch ( IOException ioException )
{
ioException.printStackTrace();
} // end catch
finally
{
closeConnection(); // close connection
} // end finally
} // end method runClient
// connect to server
private void connectToServer() throws IOException
{
displayMessage( "Attempting connection\n" ); //not getting here
// create Socket to make connection to server
client = new Socket( InetAddress.getByName( chatServer ), portNum );
// display connection information
displayMessage( "Connected to: " +
client.getInetAddress().getHostName() );
} // end method connectToServer
// get streams to send and receive data
private void getStreams() throws IOException
{
// set up output stream for objects
output = new ObjectOutputStream( client.getOutputStream() );
output.flush(); // flush output buffer to send header information
// set up input stream for objects
input = new ObjectInputStream( client.getInputStream() );
displayMessage( "\nGot I/O streams\n" );
} // end method getStreams
// process connection with server
private void processConnection() throws IOException //problem possibly due to processConnection being in infinite loop?
{
// enable enterField so client user can send messages
setTextFieldEditable( true );
do // process messages sent from server
{
try // read message and display it
{
message = input.readObject().toString(); // read new message
displayMessage( "\n" + message ); // display message
} // end try
catch ( ClassNotFoundException classNotFoundException )
{
displayMessage( "\nUnknown object type received" );
classNotFoundException.printStackTrace();
} // end catch
} while ( !message.equals( "SERVER>>> TERMINATE" ) );
} // end method processConnection
// close streams and socket
private void closeConnection()
{
displayMessage( "\nClosing connection" );
setTextFieldEditable( false ); // disable enterField
try
{
output.close(); // close output stream
input.close(); // close input stream
client.close(); // close socket
} // end try
catch ( IOException ioException )
{
ioException.printStackTrace();
} // end catch
} // end method closeConnection
// send message to server
private void sendData( String message ) //need to send filename to server
{
try // send object to server
{
output.writeObject(message);
//output.writeObject(fileName); //is writeObject the appropriate write method?
output.flush(); // flush data to output
displayMessage( "\nCLIENT>>> " + message );
} // end try
catch ( IOException ioException )
{
displayArea.append( "\nError writing object" );
ioException.printStackTrace();
} // end catch
} // end method sendData
// manipulates displayArea in the event-dispatch thread
private void displayMessage( final String messageToDisplay )
{
SwingUtilities.invokeLater(
new Runnable()
{
public void run() // updates displayArea
{
displayArea.append( messageToDisplay );
} // end method run
} // end anonymous inner class
); // end call to SwingUtilities.invokeLater
} // end method displayMessage
// manipulates enterField in the event-dispatch thread
private void setTextFieldEditable( final boolean editable )
{
SwingUtilities.invokeLater(
new Runnable()
{
public void run() // sets enterField's editability
{
enterField.setEditable( editable );
} // end method run
} // end anonymous inner class
); // end call to SwingUtilities.invokeLater
} // end method setTextFieldEditable
} // end class Client
我希望這有幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.