客户端-服务器文件传输Java
我正在尝试使用Java编写一个应用程序,它允许我在服务器和请求文件的客户机之间传输文件。我计划用插座来做。我的算法有点像这样: 在服务器上: 在客户端和服务器之间创建连接。 连接后,找到需要发送给客户端的文件。 然后将文件大小发送到客户端。 然后发送分解成部分的文件 客户 创建连接后,请求文件。 接收文件大小,然后接受数据,直到达到文件大小。 停下来客户端-服务器文件传输Java,java,sockets,client-server,protocols,Java,Sockets,Client Server,Protocols,我正在尝试使用Java编写一个应用程序,它允许我在服务器和请求文件的客户机之间传输文件。我计划用插座来做。我的算法有点像这样: 在服务器上: 在客户端和服务器之间创建连接。 连接后,找到需要发送给客户端的文件。 然后将文件大小发送到客户端。 然后发送分解成部分的文件 客户 创建连接后,请求文件。 接收文件大小,然后接受数据,直到达到文件大小。 停下来 如果我在算法中的某个地方出错,请纠正我。您还可以在收到文件的特定部分后添加来自服务器的确认, 与HTTP协议类似,这将确保在服务器上收到文件的正确
如果我在算法中的某个地方出错,请纠正我。您还可以在收到文件的特定部分后添加来自服务器的确认,
与HTTP协议类似,这将确保在服务器上收到文件的正确传递。您还可以在收到文件的特定部分后添加来自服务器的确认, 与HTTP协议类似,这将确保在服务器上收到正确的文件传递。这不是真正的“算法”问题;你正在设计一个(简单的)协议。你所描述的听起来很合理,但太模糊了,无法实现。你需要更具体一些。例如,您需要决定的一些事项:
- 接收程序如何知道它应该保存到哪个文件名?这应该通过套接字发送,还是只询问用户
- 如何传输文件大小?
- 是字符串吗?如果是,其长度是如何表示的?(使用空终止符?换行符?)
- 它是二进制值吗?如果是,有多大?(32位还是64位?)
- “分解成部分”是什么意思?如果您正在写入TCP套接字,则无需担心数据包边界;TCP解决了这个问题
- 收信人是否发回任何信息,如成功或失败指示
- 当整个文件被传输时会发生什么?
- 两端都应该假定连接必须关闭吗
- 或者可以通过一个连接发送多个文件?如果是这样,发送者如何表示另一个文件将跟随
- 接收程序如何知道它应该保存到哪个文件名?这应该通过套接字发送,还是只询问用户
- 如何传输文件大小?
- 是字符串吗?如果是,其长度是如何表示的?(使用空终止符?换行符?)
- 它是二进制值吗?如果是,有多大?(32位还是64位?)
- “分解成部分”是什么意思?如果您正在写入TCP套接字,则无需担心数据包边界;TCP解决了这个问题
- 收信人是否发回任何信息,如成功或失败指示
- 当整个文件被传输时会发生什么?
- 两端都应该假定连接必须关闭吗
- 或者可以通过一个连接发送多个文件?如果是这样,发送者如何表示另一个文件将跟随
此外,您正在反向使用术语“客户机”和“服务器”。通常,“客户端”是指启动与服务器的连接的机器,“服务器”是指等待来自客户端的连接的机器。以下是我使用的方法,它使用套接字的输入和输出流来发送和接收文件,完成后,它将自动重新启动服务器,并从客户端重新连接到服务器 服务器代码:
package app.server;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Functions
{
private static ServerSocket server;
private static Socket socket;
public static void startServer(int port)
{
try
{
server = new ServerSocket(port);
socket = server.accept();
}
catch (IOException ex)
{
Logger.getLogger(Functions.class.getName()).log(Level.SEVERE, null, ex);
}
}
private static void restartServer()
{
new Thread()
{
@Override
public void run()
{
try
{
socket = server.accept();
}
catch (IOException ex)
{
Logger.getLogger(Functions.class.getName()).log(Level.SEVERE, null, ex);
}
}
}.start();
}
public static void sendFile(String inputFilePath)
{
FileInputStream fis;
BufferedInputStream bis;
OutputStream os;
BufferedOutputStream bos;
try
{
File input = new File(inputFilePath);
fis = new FileInputStream(input);
bis = new BufferedInputStream(fis);
os = socket.getOutputStream();
bos = new BufferedOutputStream(os);
byte[] buffer = new byte[1024];
int data;
while(true)
{
data = bis.read(buffer);
if(data != -1)
{
bos.write(buffer, 0, 1024);
}
else
{
bis.close();
bos.close();
break;
}
}
}
catch (FileNotFoundException ex)
{
Logger.getLogger(Functions.class.getName()).log(Level.SEVERE, null, ex);
}
catch (IOException ex)
{
Logger.getLogger(Functions.class.getName()).log(Level.SEVERE, null, ex);
}
restartServer();
}
}
客户端代码:
package app.client;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Functions
{
private static Socket socket;
private static String hostName;
private static int portNumber;
public static void connectToServer(String host, int port)
{
new Thread()
{
@Override
public void run()
{
try
{
hostName = host;
portNumber = port;
socket = new Socket(host, port);
}
catch (IOException ex)
{
Logger.getLogger(Functions.class.getName()).log(Level.SEVERE, null, ex);
}
}
}.start();
}
private static void reconnectToServer()
{
try
{
socket = new Socket(hostName, portNumber);
}
catch (IOException ex)
{
Logger.getLogger(Functions.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void receiveFile(String outputFilePath)
{
InputStream is;
BufferedInputStream bis;
FileOutputStream fos;
BufferedOutputStream bos;
try
{
File output = new File(outputFilePath);
is = socket.getInputStream();
bis = new BufferedInputStream(is);
fos = new FileOutputStream(output);
bos = new BufferedOutputStream(fos);
byte[] buffer = new byte[1024];
int data;
while(true)
{
data = bis.read(buffer);
if(data != -1)
{
bos.write(buffer, 0, 1024);
}
else
{
bis.close();
bos.close();
break;
}
}
}
catch (IOException ex)
{
Logger.getLogger(Functions.class.getName()).log(Level.SEVERE, null, ex);
}
reconnectToServer();
}
}
这种方法非常有效,我将其用于我的服务器和客户端文件传输程序,您只需输入服务器主机的IP地址并选择端口号(我使用8888)。这是我使用的方法,它使用套接字的输入和输出流发送和接收文件,完成后,它将自动重新启动服务器,并从客户端重新连接到服务器 服务器代码:
package app.server;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Functions
{
private static ServerSocket server;
private static Socket socket;
public static void startServer(int port)
{
try
{
server = new ServerSocket(port);
socket = server.accept();
}
catch (IOException ex)
{
Logger.getLogger(Functions.class.getName()).log(Level.SEVERE, null, ex);
}
}
private static void restartServer()
{
new Thread()
{
@Override
public void run()
{
try
{
socket = server.accept();
}
catch (IOException ex)
{
Logger.getLogger(Functions.class.getName()).log(Level.SEVERE, null, ex);
}
}
}.start();
}
public static void sendFile(String inputFilePath)
{
FileInputStream fis;
BufferedInputStream bis;
OutputStream os;
BufferedOutputStream bos;
try
{
File input = new File(inputFilePath);
fis = new FileInputStream(input);
bis = new BufferedInputStream(fis);
os = socket.getOutputStream();
bos = new BufferedOutputStream(os);
byte[] buffer = new byte[1024];
int data;
while(true)
{
data = bis.read(buffer);
if(data != -1)
{
bos.write(buffer, 0, 1024);
}
else
{
bis.close();
bos.close();
break;
}
}
}
catch (FileNotFoundException ex)
{
Logger.getLogger(Functions.class.getName()).log(Level.SEVERE, null, ex);
}
catch (IOException ex)
{
Logger.getLogger(Functions.class.getName()).log(Level.SEVERE, null, ex);
}
restartServer();
}
}
客户端代码:
package app.client;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Functions
{
private static Socket socket;
private static String hostName;
private static int portNumber;
public static void connectToServer(String host, int port)
{
new Thread()
{
@Override
public void run()
{
try
{
hostName = host;
portNumber = port;
socket = new Socket(host, port);
}
catch (IOException ex)
{
Logger.getLogger(Functions.class.getName()).log(Level.SEVERE, null, ex);
}
}
}.start();
}
private static void reconnectToServer()
{
try
{
socket = new Socket(hostName, portNumber);
}
catch (IOException ex)
{
Logger.getLogger(Functions.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void receiveFile(String outputFilePath)
{
InputStream is;
BufferedInputStream bis;
FileOutputStream fos;
BufferedOutputStream bos;
try
{
File output = new File(outputFilePath);
is = socket.getInputStream();
bis = new BufferedInputStream(is);
fos = new FileOutputStream(output);
bos = new BufferedOutputStream(fos);
byte[] buffer = new byte[1024];
int data;
while(true)
{
data = bis.read(buffer);
if(data != -1)
{
bos.write(buffer, 0, 1024);
}
else
{
bis.close();
bos.close();
break;
}
}
}
catch (IOException ex)
{
Logger.getLogger(Functions.class.getName()).log(Level.SEVERE, null, ex);
}
reconnectToServer();
}
}
这种方法非常有效,我将其用于我的服务器和客户端文件传输程序,您只需输入服务器主机的IP地址并选择端口号(我使用8888)。如果是TCP套接字,有什么用?我们使用的是可靠的协议。@blackcompe它是可靠的,但您想知道文件传输是否已完成或已取消/失败/interrupted@Luiggi门多萨:是的,但如果连接中断,不会引发
IOException
吗?@blackcompe在两台机器之间执行文件传输并添加取消按钮时,当用户单击IOException时,您会抛出它吗?我担心你的设计。@Luggi Mendoza:你完全误解了我说的话。未失败的主机套接字将在对其输出流的写入(字节)
调用上抛出IOException
。我没有说过“用户点击取消按钮…”如果是TCP套接字,有什么用?我们使用的是可靠的协议。@blackcompe它是可靠的,但您想知道文件传输是否已完成或已取消/失败/interrupted@Luiggi门多萨:是的,但如果连接中断,不会引发IOException
吗?@blackcompe在两台机器之间执行文件传输并添加取消按钮时,当用户单击IOException时,您会抛出它吗?我担心你的设计。@Luggi Mendoza:你完全误解了