Java套接字:如何基于事件将多个文件从客户端发送到服务器
我正在编写一个程序,其中客户端需要监视特定文件夹中文件的创建,并在创建文件时将其发送到服务器。服务器应始终处于侦听模式,并将这些文件以相同的名称保存在服务器上的指定文件夹中。目前,我试图在同一个m/c上实现这一点。如何通过套接字实现这一点 我能够在客户端监控文件夹中文件的创建并发送它们。在接收方,我只能接收一个文件。之后,我在服务器上收到一个FileNotFoundException 客户端代码Java套接字:如何基于事件将多个文件从客户端发送到服务器,java,sockets,Java,Sockets,我正在编写一个程序,其中客户端需要监视特定文件夹中文件的创建,并在创建文件时将其发送到服务器。服务器应始终处于侦听模式,并将这些文件以相同的名称保存在服务器上的指定文件夹中。目前,我试图在同一个m/c上实现这一点。如何通过套接字实现这一点 我能够在客户端监控文件夹中文件的创建并发送它们。在接收方,我只能接收一个文件。之后,我在服务器上收到一个FileNotFoundException 客户端代码 Socket sock = new Socket("localhost", 5991);
Socket sock = new Socket("localhost", 5991);
System.out.println("Connecting.........");
Path faxFolder = Paths.get("C:\\Users\\Tushar Yadav\\Music\\src\\");
WatchService watchService = FileSystems.getDefault().newWatchService();
faxFolder.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);
boolean valid = true;
do {
WatchKey watchKey = watchService.take();
for (WatchEvent event : watchKey.pollEvents()) {
WatchEvent.Kind kind = event.kind();
if (StandardWatchEventKinds.ENTRY_CREATE.equals(event.kind())) {
String fileName = event.context().toString();
System.out.println("File Created:" + fileName);
File myFile = new File("C:\\Users\\Tushar Yadav\\Music\\src\\"+fileName);
OutputStream os = sock.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF(fileName);
dos.writeInt((int) myFile.length());
int filesize = (int) myFile.length();
byte [] buffer = new byte [filesize];
Thread.sleep(10000);
FileInputStream fis = new FileInputStream(myFile.toString());
BufferedInputStream bis = new BufferedInputStream(fis);
int count;
while ((count = fis.read(buffer)) > 0) {
dos.write(buffer, 0, count);
}
dos.flush();
}
}
valid = watchKey.reset();
}while (valid);
服务器代码
ServerSocket serverSocket = new ServerSocket(5991);
Socket clientSocket = null;
clientSocket = serverSocket.accept();
in = clientSocket.getInputStream();
clientData = new DataInputStream(in);
clientBuff = new BufferedInputStream(in);
while(true){
System.out.println("Starting...");
String fileName = clientData.readUTF();
System.out.println("filename : "+fileName);
int fileSize = clientData.read();
System.out.println("filesize is "+fileSize);
len=fileSize;
System.out.println("C:\\Users\\Tushar Yadav\\Music\\dest\\"+fileName);
output = new FileOutputStream("C:\\Users\\Tushar Yadav\\Music\\dest\\"+fileName);
dos=new DataOutputStream(output);
bos=new BufferedOutputStream(output);
byte[] buffer = new byte[1024];
bos.write(buffer, 0, buffer.length);
while (len > 0 && (smblen = clientData.read(buffer)) > 0) {
dos.write(buffer, 0, smblen);
len = len - smblen;
dos.flush();
}
dos.close();
}
我希望服务器在客户端创建另一个文件后会等待客户端发送另一个文件,但在接收者接收并保存第一个文件后不久,我会收到一个filenotfound异常
还有一个观察结果是,在服务器端,我看到了这一行System.out.println(“filename:+filename”)代码>和后续行执行两次,直到出现异常,尽管客户端只创建(并固有地发送)一个文件
以下是服务器代码的日志:-
Starting...
filename : New Text Document.txt
filesize is 0
C:\Users\Tushar Yadav\Music\dest\New Text Document.txt
Starting...
filename :
filesize is 0
C:\Users\Tushar Yadav\Music\dest\
Exception in thread "main" java.io.FileNotFoundException: C:\Users\Tushar Yadav\Music\dest (Access is denied)
at java.io.FileOutputStream.open0(Native Method)
at java.io.FileOutputStream.open(Unknown Source)
at java.io.FileOutputStream.<init>(Unknown Source)
at java.io.FileOutputStream.<init>(Unknown Source)
at test.Server.main(Server.java:55)
正在启动。。。
文件名:New Text Document.txt
文件大小为0
C:\Users\Tushar Yadav\Music\dest\New Text Document.txt
启动。。。
文件名:
文件大小为0
C:\Users\Tushar Yadav\Music\dest\
线程“main”java.io.FileNotFoundException中出现异常:C:\Users\Tushar Yadav\Music\dest(访问被拒绝)
位于java.io.FileOutputStream.open0(本机方法)
位于java.io.FileOutputStream.open(未知源代码)
位于java.io.FileOutputStream。(未知源)
位于java.io.FileOutputStream。(未知源)
位于test.Server.main(Server.java:55)
在客户端,您使用writeInt()
写入文件大小,但在服务器上,您使用read()
读取文件大小。您应该使用readInt()
。这会使一切都失去意义,因为read()
只读取4字节整数长度的第一个字节;然后你不读取任何数据,因为你认为长度是0;然后,当您尝试读取第二个文件的名称时,您的位置不正确,读取的是一个空字符串,这会导致您看到的错误。顺便说一句,使用writeLong()
和readLong()
可能更合适,因为这是File.length()
的返回类型,但这取决于您,特别是当您只使用较小的文件时
您使用DataOutputStream-dos
和BufferedOutputStream-bos
的方式似乎也有问题,这两种方法都包装了相同的FileOutputStream-output
。您首先通过bos
将未初始化的完整缓冲区写入文件(由于缓冲区已被写入,因此实际上可能只写入了部分缓冲区);然后,您再次通过dos
读取和写入实际的文件数据,该数据将附加到先前写入输出的数据中。也许您的意思是像dos=newdataoutputstream(new BufferedOutputStream(output))
这样的东西,这会给您带来两者的好处。但您仍然不希望像以前那样在读取循环之前写入整个未初始化的缓冲区
此外,由于您只使用了write()
,因此您可能可以直接使用output.write()
,而无需复杂的DataOutputStream。如果您希望避免频繁地对磁盘进行小规模写入,则BufferedOutputStream作为一种优化非常有用,但这不是必需的,特别是因为在读取/写入1Kb块的方式中存在一些固有的缓冲