我需要为我的项目创建一个带套接字的文件传输应用程序。到目前为止,我已经编写了一个简单的客户端 - 服务器通信,但每当我尝试从客户端输出到服务器输入接收字符数据时,我的代码就会锁定。下面是代码:
服务器
public class ClientServer extends Thread {
Socket connection;
File file;
public ClientServer (Socket connection){
this.connection = connection;
this.start();
}
public void run(){
try {
System.out.println("Starting Client Thread...");
BufferedReader input = new BufferedReader(new InputStreamReader(connection.getInputStream()));
DataOutputStream output = new DataOutputStream(connection.getOutputStream());
System.out.println("IO created...");
System.out.println("input = " + input.readLine());
String s = input.readLine();
System.out.println(s);
file = new File(s);
if(file.isFile()){
System.out.println("File " + s + " exists");
FileInputStream fileOutput = new FileInputStream(file);
byte[] buffer = new byte[1024*1024];
int length = 0;
while((length = fileOutput.read(buffer)) != -1){
output.write(buffer, 0, buffer.length);
}
System.out.println("File " + s + " sent.");
fileOutput.close();
output.close();
input.close();
} else {
System.out.println(s + " is not a file");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
finally{
try {
connection.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException {
int serverPort = 9000;
ServerSocket server = new ServerSocket(serverPort);
Socket connectionSocket = server.accept();
ClientServer con = new ClientServer(connectionSocket);
}
}
客户端
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
String ip = "localhost";
int port = 9000;
Socket clientSocket = new Socket(ip, port);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
DataInputStream in = new DataInputStream(clientSocket.getInputStream());
BufferedReader userInput = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter valid file name and press 'ENTER': ");
String message = userInput.readLine();
System.out.println("Sending message...");
out.write(message);
System.out.println("File name sent: " + message);
int length = in.readInt();
byte[] buffer = new byte[length];
for(int i=0; i< length; i++){
buffer[i] = in.readByte();
System.out.println("Reading byte... " + buffer[i]);
}
File file = new File("C:/Users/Dominik/Desktop/lol/new.php");
FileOutputStream fos = new FileOutputStream(file);
fos.write(buffer);
fos.close();
clientSocket.close();
System.out.println("Closing");
}
}
修改
这是我的输出,因为没有一个答案能解决我的问题(可能是我做错了):
客户端
Enter valid file name and press 'ENTER':
C:\\Users\\Dominik\\Desktop\\Login.php //my input
Sending message...
File name sent: C:\\Users\\Dominik\\Desktop\\Login.php
服务器
Starting Client Thread...
IO created...
//Server should sysout the message sent, but it doesn't do so, its just stuck here
答案 0 :(得分:1)
您尝试在客户端readInt
,但在服务器端,您只发送文件内容。在发送文件之前,我看起来忘了发送文件大小。
答案 1 :(得分:1)
你正在读一句话:
String s = input.readLine();
但你不是在写一行:
out.write(message);
为此添加行终止符。
然后:
int length = in.readInt();
在这里,您正在读取一个永不发送的整数。发送它。
答案 2 :(得分:1)
我认为你的通信协议有错误:
在您的服务器中,连接后,您需要来自客户端的两个后续字符串
System.out.println("input = " + input.readLine());
String s = input.readLine();
但是客户端只发送一个(我认为你应该按照EJP的建议添加一个行终止符)
然后客户端需要一个整数,但服务器没有发送它:
int length = in.readInt();
希望它有所帮助,祝你好运
修改(在12月23日编辑之后)
添加到您的客户端
out.flush();
之后
out.write(message + "\n");
然后修复协议。
我应用了你得到的所有建议,并让我开始工作
服务器:
public class ClientServer extends Thread {
Socket connection;
File file;
public ClientServer(Socket connection) {
this.connection = connection;
start();
}
@Override
public void run() {
try {
System.out.println("Starting Client Thread...");
BufferedReader input = new BufferedReader(new InputStreamReader(connection.getInputStream()));
DataOutputStream output = new DataOutputStream(connection.getOutputStream());
System.out.println("IO created...");
// System.out.println("input = " + input.readLine());
String s = input.readLine();
System.out.println(s);
file = new File(s);
if (file.isFile()) {
System.out.println("File " + s + " exists");
FileInputStream fileInput = new FileInputStream(file);
output.writeInt((int) file.length());
byte[] buffer = new byte[1024 * 1024];
int length = 0;
while ((length = fileInput.read(buffer)) != -1) {
output.write(buffer, 0, length);
}
System.out.println("File " + s + " sent.");
fileInput.close();
output.close();
input.close();
}
else {
System.out.println(s + " is not a file");
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
finally {
try {
connection.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException {
int serverPort = 9000;
ServerSocket server = new ServerSocket(serverPort);
Socket connectionSocket = server.accept();
ClientServer con = new ClientServer(connectionSocket);
}
}
客户端:
public class Client {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
String ip = "localhost";
int port = 9000;
Socket clientSocket = new Socket(ip, port);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
DataInputStream in = new DataInputStream(clientSocket.getInputStream());
BufferedReader userInput = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter valid file name and press 'ENTER': ");
String message = userInput.readLine();
System.out.println("Sending message...");
out.write(message + "\n");
out.flush();
System.out.println("File name sent: " + message);
int length = in.readInt();
byte[] buffer = new byte[length];
for (int i = 0; i < length; i++) {
buffer[i] = in.readByte();
System.out.println("Reading byte... " + buffer[i]);
}
File file = new File("C:/test/fromServer.txt");
FileOutputStream fos = new FileOutputStream(file);
fos.write(buffer);
fos.close();
clientSocket.close();
System.out.println("Closing");
}
}
答案 3 :(得分:0)
只是对所有有用答案的一小部分补充:
在服务器端写option
个字节的文件 - length
不要使用buffer.length,这通常会导致output.write(buffer, 0, length);
因为客户端会在收到java.net.SocketException: Broken pipe
字节后立即关闭套接字,但服务器正在尝试写入整个1024 * 1024缓冲区。
同样在客户端,你可以摆脱for循环并接收像这样的文件内容
length