Java ソケットとServerSocket
ライブラリを使用して簡単なファイル転送プログラムを作成しようとしています。以前にこれらのライブラリを正常に使用したことがありますが、この場合、クライアント側が要求を行うために接続が確立されると、サーバー側が十分に遅くなるのに問題があるようです。この問題は、サーバー側のメイン メソッドが 2 番目の while ループに入り、 を呼び出しhandleRequest()
、に入るとhandleRequest()
、SocketExeption
クライアントのリクエストを読み込もうとするとエラーが発生します。プログラムは、クライアント側のユーザーが要求を送信できるほど長く一時停止しません。メインの 2 番目の while ループ内でコードを移動しようとしましたが、役に立ちませんでした。サーバー側の速度を落としてリッスンするための助けをいただければ幸いです。ありがとう!
編集: スローされる例外は次のとおりです。
Exception in thread "main" java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
at sun.nio.cs.StreamDecoder.read(Unknown Source)
at java.io.InputStreamReader.read(Unknown Source)
at java.io.BufferedReader.fill(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at FTServe.handleRequest(FTServe.java:92)
at FTServe.main(FTServe.java:218)
編集を終了
これが私のコードです:
サーバ側
import java.net.*;
import java.io.*;
public class FTServe {
BufferedReader stdIn;
static BufferedReader in = null;
static PrintWriter out = null;
static ServerSocket serverSocket;
FTServe() {
}
/**********************************************************
* Desc: starts on host A, validates the parameter, and waits on port
* 30021 for client request
* Parameters:
* Returns:
* @param portNum
**********************************************************
*/
private Socket startUp(int portNum) throws IOException {
serverSocket = null;
Socket clientSocket = null;
//server to listen on port 30021
//ftserve starts on host A, and validates the command-line parameters.
try {
serverSocket = new ServerSocket(portNum);
System.out.println("Waiting for client....");
} catch (IOException e) {
System.err.println("Could not listen on port: " + portNum);
System.exit(1);
}
//waits for client message and accepts connection (client IP address and port)
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
return clientSocket;
}
/**********************************************************
* Desc: accepts, interprets and handles client requests
* Parameters:
* Returns:
* @param server
* @param server
* @throws IOException
**********************************************************
*/
public static void handleRequest(FTServe server) throws IOException {
Socket dataSocket = null;
String message = in.readLine();
if (message != null) {
if (message.equalsIgnoreCase("list")) {
int portNum = 30020;
dataSocket = server.startUp(portNum);
sendDirectory();
}
else if (message.contains("get <")) {
int j = 0;
String requestedFile = null;
char letter;
String prefix = "get <";
requestedFile = message.substring(message.indexOf(prefix + prefix.length(), message.length()-2));
//open port 30020 to send data to client
dataSocket = server.startUp(30020);
sendFile(dataSocket, requestedFile);
}
else {
out.println("Invalid command. Please enter 'list' or 'get <filename>: ");
}
dataSocket.close();
}
}
/**********************************************************
* Desc: sends list of files in directory to client
* Parameter: String requestedFile, Socket dataSocket
* Returns:
* @param dataSocket
* @param requestedFile
* @throws IOException
**********************************************************
*/
private static void sendDirectory() {
String path = new File(".").getAbsolutePath();
File dir = new File(path);
File[] listFiles = dir.listFiles();
for (int i = 0; i < listFiles.length; i++) {
if (listFiles[i].isFile()) {
String fileName = listFiles[i].getName();
out.print(fileName + " ");
}
}
}
/**********************************************************
* Desc: sends file to client on port 30020
* Parameter: String requestedFile, Socket dataSocket
* Returns:
* @param dataSocket
* @param requestedFile
* @throws IOException
**********************************************************
*/
private static void sendFile(Socket dataSocket, String requestedFile) throws IOException {
File sendFile = new File(requestedFile);
if (sendFile.isFile()){
byte[] fileByteArray = new byte[(int) requestedFile.length()];
FileInputStream fis = new FileInputStream(requestedFile);
BufferedInputStream bis = new BufferedInputStream(fis);
DataInputStream dis = new DataInputStream(bis);
dis.readFully(fileByteArray, 0, fileByteArray.length);
//opens output stream and sends file info and file to the client
OutputStream os = dataSocket.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF(sendFile.getName());
dos.writeLong(fileByteArray.length);
dos.write(fileByteArray, 0, fileByteArray.length);
dos.flush();
}
else out.println("That is not a valid filename.");
}
/***********************************************************
* Desc: closes server socket
* Parameter: serverSocket
**********************************************************
*/
private void closeSocket(ServerSocket serverSocket) throws IOException {
serverSocket.close();
}
/***********************************************************
* Desc: Main method
**********************************************************
*/
public static void main(String[] args) throws IOException {
int goodbye = 0; //if goodbye == 1, close client connection; if goodbye == -1, close server socket
while (goodbye != -1) {
goodbye = 0;
FTServe server = new FTServe();
Socket socket = null;
int portNum = 30021;
socket = server.startUp(portNum);
String message;
System.out.println("When you wish to disconnect from client, simply enter 'bye'. \nTo close socket, enter 'exit'.");
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Connection from " + socket.getLocalAddress().getHostName() + " successful. \n\nWaiting on client...");
//gets inputs and outputs from client
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (goodbye == 0) {
server.handleRequest(server);
//close connection to client if goodbye == 1 because server entered bye
if (goodbye == 1) {
System.out.println("Connection to client closing...");
out.println("Connection to client closing...Goodbye");
in.close();
out.close();
socket.close();
server.closeSocket(serverSocket);
}
}
//server.startUp();
System.out.println("Enter 'exit' to close, else enter 'go' to continue listening for client. When server is listening, Ctrl-C will end program");
System.out.print("Server> ");
if (stdIn.readLine().equals("exit")) {
server.closeSocket(serverSocket);
goodbye = -1;
}
}
System.out.println("The program is closing. Goodbye!");
}
}
クライアント側
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class FTClient {
static BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
static PrintWriter out = null;
static BufferedReader in = null;
FTClient() {
}
/**********************************************************
* Desc: initiates contact with server
* Parameter: iPadd == server IP address, portNum == server port
* Returns: Client socket
**********************************************************
*/
private Socket initiateContact (String iPadd, int portNum) throws IOException {
Socket clientSocket = null;
//ftclient starts on host B, and validates the command-line parameters.
try {
//create connection between client and server
clientSocket = new Socket(iPadd, portNum);
} catch (UnknownHostException e) {
System.err.println("Don't know about host: " + iPadd + ".");
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to: " + iPadd + ".");
System.exit(1);
}
return clientSocket;
}
/**********************************************************
*Desc: sends client message to server
*Parameter: String msg
*Returns: Boolean true if client message == bye, else false
**********************************************************
*/
private boolean sendMessage(String fromUser) throws IOException {
if (fromUser.equals("bye")) {
out.println("Client> " + fromUser);
return true;
}
else if (fromUser != null) out.println("Client> " + fromUser);
return false;
}
/**********************************************************
* Desc: sends client command: 'list or get <filename>'
* Parameters:
* Returns:
* @param request
* @return
* @throws IOException
**********************************************************
*/
private boolean makeRequest(String request) throws IOException {
//ftclient sends a command (list or get <filename>) on connection to port 30020.
if (request.equals("bye")) {
out.println(request);
return true;
}
else if (request != null) out.println(request);
return false;
}
/**********************************************************
* Desc: saves the file in the current default directory (handling "duplicate file name" error if necessary),
* and displays a "transfer complete" message on-screen or sends an appropriate error message
* (“File not found”, etc.) to ftclient on connection P, and ftclient displays the message on-screen.
* Parameters:
* Returns:
* @return
* @throws IOException
**********************************************************
*/
private void receiveFile()
{
//code remains to be written
}
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
FTClient client = new FTClient();
boolean goodbye = false;
Socket socket, datasocket;
String iPadd = args[0];
String port = args[1];
int portNum = Integer.parseInt(port);
//initate contact with server
socket = client.initiateContact(iPadd, portNum);
System.out.println("When you wish to exit, simply enter 'bye'.");
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//client sends request, then initiates contact with data socket to receive data
while (!goodbye) {
System.out.println("Server> Enter 'list' to display a directory of files. \nEnter 'get <filename>' to retrieve a file. " +
"\nPlease enter a command: ");
String request = stdIn.readLine();
goodbye = client.makeRequest(request);
int dataPort = 30020;
Socket dataSocket = client.initiateContact(iPadd, dataPort);
client.receiveFile();
}
}
}