文件传输-Java套接字编程

文件传输-Java套接字编程,java,file,sockets,Java,File,Sockets,我有以下服务器和客户端代码。客户机尝试将大小为2000B的文件“testprgm.txt”传输到服务器,并将其保存为“Test.txt”。问题是,我可以看到服务器和客户端上的字节传输,但当我运行这些代码后看到Test.txt文件的大小时,它是零 服务器程序: import java.io.*; 导入java.net。*; 公共类服务器测试{ 公共静态void main(字符串[]args){ System.out.println(“*************服务器程序*************”

我有以下服务器和客户端代码。客户机尝试将大小为2000B的文件“testprgm.txt”传输到服务器,并将其保存为“Test.txt”。问题是,我可以看到服务器和客户端上的字节传输,但当我运行这些代码后看到Test.txt文件的大小时,它是零

服务器程序:
import java.io.*;
导入java.net。*;
公共类服务器测试{
公共静态void main(字符串[]args){
System.out.println(“*************服务器程序*************”);
int byteRead=0;
试一试{
ServerSocket ServerSocket=新的ServerSocket(9999);
如果(!serverSocket.isBound())
System.out.println(“服务器套接字未绑定…”);
其他的
System.out.println(“绑定到端口的服务器套接字:”+serverSocket.getLocalPort());
Socket clientSocket=serverSocket.accept();
如果(!clientSocket.isConnected())
System.out.println(“客户端套接字未连接…”);
其他的
System.out.println(“连接的客户端套接字:+clientSocket.getInetAddress());
while(true){
InputStream in=clientSocket.getInputStream();
OutputStream os=新文件OutputStream(“/Test.txt”);
byte[]byteArray=新字节[100];
while((byteRead=in.read(byteArray,0,byteArray.length))!=-1){
写操作系统(byteArray,0,byteRead);
System.out.println(“接收的字节数:“+byteRead”);
}
已同步(操作系统){
等待(100);
}
os.close();
serverSocket.close();
//System.out.println(“文件已接收…”);
}
}捕获(例外e){
System.out.println(“服务器异常:+e.getMessage());
e、 printStackTrace();
}
}
}
客户端程序:
import java.io.*;
导入java.net。*;
公共类客户端{
公共静态void main(字符串[]args)
{
插座;
尝试
{
套接字=新套接字(“服务器IP地址>”,9999);
如果(!socket.isConnected())
System.out.println(“未建立套接字连接”);
其他的
System.out.println(“已建立套接字连接:+Socket.getInetAddress());
File myfile=new File(“/testprgm.txt”);//本地文件路径。
如果(!myfile.exists())
System.out.println(“文件不存在”);
其他的
System.out.println(“文件存在”);
字节[]字节数组=新字节[1024];
FileInputStream fis=新的FileInputStream(myfile);
BufferedInputStream bis=新的BufferedInputStream(fis);
OutputStream os=socket.getOutputStream();
int trxBytes=0;
while((trxBytes=bis.read(byteArray,0,byteArray.length))!=-1)
{           
写操作(byteArray,0,byteArray.length);
System.out.println(“传输字节:+trxBytes”);
}
os.flush();
二、关闭();
socket.close();
System.out.println(“文件传输…”);
}
捕获(例外e)
{
System.out.println(“客户端异常:+e.getMessage());
}       
}
}

您的服务器复制循环是正确的,因为它在
write()
方法调用中使用了
read()
返回的计数。客户端复制循环也应该这样做。没有

在任何情况下,您的协议都是基于谬误的<套接字输入流上的code>read()将在对等方关闭连接时返回-1,而不是之前。因此,将一个在
read()
返回-1时终止的循环放在使用相同连接的另一个循环中是不可能工作的。似乎您正试图通过一个连接发送多个文件。您需要在每个文件之前发送长度,并且只读取每个文件的确切字节数


否则,您需要在发送单个文件后关闭连接,并删除接收器中的外部环路。

我将使用NIO进行文件传输,因为它更短、更高效。以下是客户端:

    try (SocketChannel sc = SocketChannel.open(new InetSocketAddress(
            hostaddress, 9999));
            FileChannel fc = new FileInputStream("test").getChannel()) {
        fc.transferTo(0, fc.size(), sc);
    }
    System.out.println("File Transfered...");
服务器端:

    ServerSocketChannel ss = ServerSocketChannel.open();
    ss.bind(new InetSocketAddress("localhost", 9999));
    try (SocketChannel sc = ss.accept();
            FileChannel fc = new FileOutputStream("test").getChannel()) {
        fc.transferFrom(sc, 0, Long.MAX_VALUE);
    }

您的
if
语句是奇数。在出现错误的情况下打印一条消息,然后继续执行程序。您应该真正退出方法(使用
返回;
或引发异常)。您忽略了
trxBytes
可能介于1和99之间的事实。这将损坏文件。@PeterLawrey实际上介于1和1024之间。@EJP出于某种原因,我读取了
新字节[100]
。我在客户端使用了您的代码。但在传输字节的同时,我仍然在服务器上获取大小为零的文件。您不应该一次读取一个字节的套接字输入流:这是最低效的。需要在循环中调用transferTo()。不能保证在一次调用中传输整个长度。@EJP不能保证只传输非阻塞通道。FileChannel始终处于阻塞状态,SocketCannel始终处于阻塞状态default@EvgeniyDorofeev根本不能保证。如果您不这么认为,请引用相关措辞。
    try (SocketChannel sc = SocketChannel.open(new InetSocketAddress(
            hostaddress, 9999));
            FileChannel fc = new FileInputStream("test").getChannel()) {
        fc.transferTo(0, fc.size(), sc);
    }
    System.out.println("File Transfered...");
    ServerSocketChannel ss = ServerSocketChannel.open();
    ss.bind(new InetSocketAddress("localhost", 9999));
    try (SocketChannel sc = ss.accept();
            FileChannel fc = new FileOutputStream("test").getChannel()) {
        fc.transferFrom(sc, 0, Long.MAX_VALUE);
    }