我正在尝试使用Java Socket和ServerSocket
库编写一个简单的文件传输程序。我以前曾经成功地使用过这些库,但在这种情况下,一旦建立连接以便客户端发出请求,我似乎很难让服务器端放慢足够长的时间。问题似乎正在发生,因为服务器端的 main 方法进入第二个 while 循环,调用handleRequest()
,并且一旦进入handleRequest()
,抛出一个SocketExeption
尝试读取客户端请求时出错。程序没有暂停足够长的时间以允许客户端的用户发送请求。我尝试在 main 的第二个 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();
}
}
}