Java 套接字传输文件

Java 套接字传输文件,java,sockets,serversocket,Java,Sockets,Serversocket,我有一个Java服务器类,如下所示: ServerSocket servsock = new ServerSocket(63456); boolean read = false; while (!read) { Socket sock = servsock.accept(); int length = 1024; byte[] mybytearray = new byte[length]; OutputStream os = sock.getOutputStrea

我有一个Java服务器类,如下所示:

ServerSocket servsock = new ServerSocket(63456);
boolean read = false;
while (!read) {
    Socket sock = servsock.accept();
    int length = 1024;
    byte[] mybytearray = new byte[length];
    OutputStream os = sock.getOutputStream();
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myFile));
    while (true) {
    int i = bis.read(mybytearray, 0, mybytearray.length);
    if (i == 1) {
        break;
    }
    os.write(mybytearray, 0, mybytearray.length);
    os.flush();
    }
    sock.close();
    read = true;
}
Socket sock = new Socket("127.0.0.1", 63456);
byte[] mybytearray = new byte[1024];
InputStream is = sock.getInputStream();
FileOutputStream fos = new FileOutputStream("C:/tmp/NEWtmp.rar");
BufferedOutputStream bos = new BufferedOutputStream(fos);
int bytesRead = is.read(mybytearray, 0, mybytearray.length);
while(bytesRead != -1 ) {
    bos.write(mybytearray, 0, bytesRead);
    bytesRead = is.read(mybytearray, 0, mybytearray.length);
}
bos.close();
sock.close();
` 客户是这样的:

ServerSocket servsock = new ServerSocket(63456);
boolean read = false;
while (!read) {
    Socket sock = servsock.accept();
    int length = 1024;
    byte[] mybytearray = new byte[length];
    OutputStream os = sock.getOutputStream();
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myFile));
    while (true) {
    int i = bis.read(mybytearray, 0, mybytearray.length);
    if (i == 1) {
        break;
    }
    os.write(mybytearray, 0, mybytearray.length);
    os.flush();
    }
    sock.close();
    read = true;
}
Socket sock = new Socket("127.0.0.1", 63456);
byte[] mybytearray = new byte[1024];
InputStream is = sock.getInputStream();
FileOutputStream fos = new FileOutputStream("C:/tmp/NEWtmp.rar");
BufferedOutputStream bos = new BufferedOutputStream(fos);
int bytesRead = is.read(mybytearray, 0, mybytearray.length);
while(bytesRead != -1 ) {
    bos.write(mybytearray, 0, bytesRead);
    bytesRead = is.read(mybytearray, 0, mybytearray.length);
}
bos.close();
sock.close();
一个问题是:为什么循环不在文件末尾停止?
第二个问题是,为什么它也这么慢?

它不会停止,因为

if (i == 1) {
在您的服务器中,源代码应该是

if (i == -1) {
或者,如果你想真正安全:

if (i <= 0) {
您应该将此更改为:

os.write(mybytearray, 0, i);

在性能方面——移动
os.flush()调用外部
while
循环。当您刷新网络流时,您强制它将任何缓冲数据发送到网络。这迫使网络层发送和确认1024字节的TCP有效负载(当然,更大的以太网有效负载),这可能比PMTU小得多。您只需要在发送完数据或希望客户端立即接收缓冲数据时进行刷新。从每次迭代中删除刷新调用将允许操作系统级网络缓冲区完成其工作,并将数据分段为尽可能少的数据包。

它不会停止,因为

if (i == 1) {
在您的服务器中,源代码应该是

if (i == -1) {
或者,如果你想真正安全:

if (i <= 0) {
您应该将此更改为:

os.write(mybytearray, 0, i);

在性能方面——移动
os.flush()调用外部
while
循环。当您刷新网络流时,您强制它将任何缓冲数据发送到网络。这迫使网络层发送和确认1024字节的TCP有效负载(当然,更大的以太网有效负载),这可能比PMTU小得多。您只需要在发送完数据或希望客户端立即接收缓冲数据时进行刷新。从每次迭代中删除刷新调用将允许操作系统级网络缓冲区执行其工作,并将数据分段为尽可能少的数据包。

第二个问题-您的客户端直接从原始套接字流读取字节。使用BufferedInputStream/BufferedOutputStream装饰器,这将提高性能:

服务器端

BufferedOutputStream os = new BufferedOutputStream(sock.getOutputStream());
BufferedInputStream is = new BufferedInputStream(sock.getInputStream());
客户端

BufferedOutputStream os = new BufferedOutputStream(sock.getOutputStream());
BufferedInputStream is = new BufferedInputStream(sock.getInputStream());

原始流没有缓冲(AFAIK),因此如果需要,您必须手动添加缓冲。

第二个问题-您的客户端直接从原始套接字流读取字节。使用BufferedInputStream/BufferedOutputStream装饰器,这将提高性能:

服务器端

BufferedOutputStream os = new BufferedOutputStream(sock.getOutputStream());
BufferedInputStream is = new BufferedInputStream(sock.getInputStream());
客户端

BufferedOutputStream os = new BufferedOutputStream(sock.getOutputStream());
BufferedInputStream is = new BufferedInputStream(sock.getInputStream());

未经缓冲的原始流(AFAIK),因此如果需要,您必须手动添加缓冲。

是,这增加了一些速度。太简单了;-)无论如何,我应该亲自去看看,谢谢。是的,这增加了一些速度。太简单了;-)无论如何,我应该亲自去看的,谢谢你。