将文件传输到java客户端后保持套接字连接打开
在学校里,我们有一个项目,我们必须将文件从服务器发送到客户端。问题是,当我们将文件从服务器传输到客户端时,服务器会关闭连接。以下是我们目前的代码: 客户:将文件传输到java客户端后保持套接字连接打开,java,file,sockets,socketexception,Java,File,Sockets,Socketexception,在学校里,我们有一个项目,我们必须将文件从服务器发送到客户端。问题是,当我们将文件从服务器传输到客户端时,服务器会关闭连接。以下是我们目前的代码: 客户: public static void main(String argv[]) throws Exception { int port = 8888; //default if (argv.length > 0) { port = Integer.parseInt(arg
public static void main(String argv[]) throws Exception {
int port = 8888; //default
if (argv.length
> 0) {
port = Integer.parseInt(argv[0]);
}
Socket clientSocket = new Socket("127.0.0.1", port);
PrintStream outToServer = new PrintStream(
clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
File f = new File("dictionaryPart.txt");
String serverCommand = inFromServer.readLine().toLowerCase();
while (serverCommand != null) {
System.out.println(serverCommand);
switch (serverCommand) {
case "velkommen":
outToServer.println("Hej");
break;
case "file":
f = copy(clientSocket, f);
String matches = CrackerCentralized.checkFile(f);
System.out.println(matches);
outToServer.println(matches);
break;
}
serverCommand = inFromServer.readLine().toLowerCase();
}
}
public static File copy(Socket clientSocket, File f) {
try {
int filesize = 2022386;
int bytesRead;
int currentTot = 0;
byte[] buffer = new byte[filesize];
InputStream is = clientSocket.getInputStream();
FileOutputStream fos = new FileOutputStream(f);
BufferedOutputStream bos = new BufferedOutputStream(fos);
bytesRead = is.read(buffer, 0, buffer.length);
currentTot = bytesRead;
while (bytesRead != -1) {
bytesRead = is.read(buffer, currentTot, (buffer.length - currentTot));
if (bytesRead >= 0) {
currentTot += bytesRead;
}
}
bos.write(buffer, 0, currentTot);
bos.flush();
bos.close();
} catch (IOException ex) {
Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
}
return f;
}
服务器:
try {
PrintStream outToClient = new PrintStream(connection.getOutputStream());
OutputStream os = connection.getOutputStream();
BufferedInputStream input = new BufferedInputStream(new FileInputStream(f));
outToClient.println("file");
final byte[] buffer = new byte[(int) f.length()];
input.read(buffer, 0, buffer.length);
os.write(buffer, 0, buffer.length);
os.write(-1);
os.flush();
System.out.println(connection.isClosed());
os.close();
System.out.println(connection.isClosed());
} catch (IOException ex) {
Logger.getLogger(SocketController.class.getName()).log(Level.SEVERE, null, ex);
}
我知道为什么连接一直关闭。我们通过写入来关闭套接字的输出
output.close();
但是我不知道我们必须以什么其他方式尝试这样做,以使服务器继续侦听客户端的答案(匹配/不匹配),以便服务器知道它是否应该发送更多文件,或者客户端是否成功。。甚至可以在不关闭与服务器的连接的情况下发送at文件吗?过去两天我在谷歌上搜索了一整天,一点运气都没有
谢谢你的阅读和帮助 为了实现您的要求,您需要建立一个服务器和客户端都能理解的通信协议。需要传输的内容包括“我开始向您发送信息”和“我已完成发送内容”的内容。可能还有更多内容,例如信息定界(例如Mime多部分表单边界)。但至少,您需要启动和停止令牌。
在此基础上展开:以最简单的形式查看代码:
server:loop{write()}->client:loop{read()}
。关闭服务器端的流会向客户端发送-1值,该值通常作为停止信号使用。如果您希望无限期地维护连接,并在不同的时间向客户机写入数据,则必须发送一些内容,说明“此事务已完成”。以下是伪ish代码——手绘,未编译
// SERVER
private Socket socket; // initialized somewhere
private static final byte[] STOP = "</COMMS>".getBytes();
public void sendData(byte[] bytes) throws IOException{
OutputStream out = socket.getOutputStream();
if(bytes != null){
out.write(bytes,0,bytes.length);
}
out.write(STOP);
} // notice we exit the method without closing the stream.
//服务器
专用套接字;//在某处初始化
私有静态最终字节[]STOP=“.getBytes();
公共void sendData(字节[]字节)引发IOException{
OutputStream out=socket.getOutputStream();
如果(字节数!=null){
out.write(字节、0、字节、长度);
}
写出(停止);
}//注意,我们在不关闭流的情况下退出了该方法。
//客户端
专用套接字;//在某处初始化
私有静态最终字节[]STOP=“.getBytes();
private static final int BUFFER_SIZE=1024感谢madConan的回复,它给了我一个很好的方法。我将在这里发布我的代码,以便其他人将来可以使用它
服务器代码
public void run() {
try {
PrintStream outToClient = new PrintStream(connection.getOutputStream());
OutputStream os = connection.getOutputStream();
BufferedInputStream input = new BufferedInputStream(new FileInputStream(f));
outToClient.println("file");
copy(input, os, f);
System.out.println(connection.isClosed());
} catch (IOException ex) {
Logger.getLogger(SocketController.class.getName()).log(Level.SEVERE, null, ex);
}
}
private static void copy(final InputStream is, final OutputStream os, File f) throws IOException {
final byte[] stop = "stop".getBytes();
final byte[] buffer = new byte[(int) f.length()];
is.read(buffer, 0, buffer.length);
os.write(buffer, 0, buffer.length);
os.write(stop);
os.flush();
}
客户端代码
public static File recieveData(Socket clientSocket, File f) {
try {
InputStream in = clientSocket.getInputStream();
FileOutputStream output = new FileOutputStream(f);
byte[] content;
byte[] bytes = new byte[1024 << 8];
int bytesRead;
while (true) {
if (recieveStop(f)) {
removeStop(f);
break;
}
bytesRead = in.read(bytes);
output.write(bytes, 0, bytesRead);
}
} catch (IOException ex) {
Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
}
return f;
}
public static boolean recieveStop(File f) {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(f));
String currentLine;
String lastLine = "";
while ((currentLine = br.readLine()) != null) {
lastLine = currentLine;
}
if (lastLine.equals("stop")) {
return true;
}
} catch (FileNotFoundException ex) {
Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
br.close();
} catch (IOException ex) {
Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
return false;
}
public static void removeStop(File f) {
try {
RandomAccessFile raFile = new RandomAccessFile(f, "rw");
long length = raFile.length();
raFile.setLength(length - 4);
raFile.close();
} catch (FileNotFoundException ex) {
Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
公共静态文件receiveData(套接字客户端套接字,文件f){
试一试{
InputStream in=clientSocket.getInputStream();
FileOutputStream输出=新的FileOutputStream(f);
字节[]内容;
字节[]字节=新字节[1024我不知道这是否太多,但你能提供一个如何实现这一点的示例,或者告诉我更多关于它的信息吗?我对套接字编程非常陌生,我不确定我是否理解你的意思。+1用于建立应用程序协议的需要。分隔符不是协议中框显消息的唯一方法,你也可以简单地为正在传输的消息的长度添加前缀,以便接收方知道要读取多少字节。有一件事:您可能不知道使用“stop”作为令牌的内容,除非您确实确定有效负载永远不会包含“stop”.哦,是的,谢谢你,我没有真的考虑过它…它有时可能不包含它..嘿,乌尔博…不确定你是否会记住这一点,但你是如何让你的循环实际中断的?我的循环只是冻结,似乎没有达到中断点。嗨@Visionwriter。我所做的是使用停止信号。在这种情况下,我使用了“停止”正如MadConan指出的那样,信号不是最好的主意,除非你绝对确定你的有效载荷中没有这个词。谢谢,伙计。终于弄明白了。我没有阅读文本,所以我不能使用readLine。最后在读取空缓冲区之前,使用文件大小作为测试,它工作了。不过,谢谢。
public static File recieveData(Socket clientSocket, File f) {
try {
InputStream in = clientSocket.getInputStream();
FileOutputStream output = new FileOutputStream(f);
byte[] content;
byte[] bytes = new byte[1024 << 8];
int bytesRead;
while (true) {
if (recieveStop(f)) {
removeStop(f);
break;
}
bytesRead = in.read(bytes);
output.write(bytes, 0, bytesRead);
}
} catch (IOException ex) {
Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
}
return f;
}
public static boolean recieveStop(File f) {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(f));
String currentLine;
String lastLine = "";
while ((currentLine = br.readLine()) != null) {
lastLine = currentLine;
}
if (lastLine.equals("stop")) {
return true;
}
} catch (FileNotFoundException ex) {
Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
br.close();
} catch (IOException ex) {
Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
return false;
}
public static void removeStop(File f) {
try {
RandomAccessFile raFile = new RandomAccessFile(f, "rw");
long length = raFile.length();
raFile.setLength(length - 4);
raFile.close();
} catch (FileNotFoundException ex) {
Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
}
}