简体   繁体   English

套接字传输文件

[英]Socket transferring a file

I have a Java server class like this: 我有一个这样的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;
}

` And the client is like this: 和客户是这样的:

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();

One question is: Why the loop does not stop at the end of the file? 一个问题是:为什么循环不会在文件末尾停止? A second question would be, why is also so slow? 第二个问题是,为什么还这么慢?

It does not stop because 它不会停止,因为

if (i == 1) {

in your server source should be 您的服务器源中应该是

if (i == -1) {

Or, if you want to be really safe: 或者,如果您想真正安全:

if (i <= 0) {

Also, you risk data corruption with this line: 此外,您可能会在此行中冒数据损坏的风险:

os.write(mybytearray, 0, mybytearray.length);

You should change this to: 您应该将其更改为:

os.write(mybytearray, 0, i);

On performance -- move the os.flush(); 性能上-移动os.flush(); call to outside the while loop. while循环外调用。 When you flush a network stream, you are forcing it to dispatch any buffered data to the network. 刷新网络流时,将强制其将所有缓冲的数据分发到网络。 This is forcing the network layer to send and acknowledge 1024-byte TCP payloads (larger Ethernet payloads, of course) which is probably significantly smaller than your PMTU. 这迫使网络层发送和确认1024字节的TCP有效负载(当然,更大的以太网有效负载)可能比PMTU小得多。 You only need to flush when you are done sending data, or when you want the client to receive the buffered data now . 仅在完成发送数据后或希望客户端现在接收缓冲的数据时才需要刷新。 Removing the flush call from each iteration will allow the OS-level network buffer to do its job, and segment the data into as few packets as possible. 从每个迭代中删除刷新调用将允许OS级网络缓冲区执行其工作,并将数据分段为尽可能少的数据包。

Second question - your client reads bytes directly from the raw socket stream. 第二个问题-您的客户端直接从原始套接字流读取字节。 Use the BufferedInputStream/BufferedOutputStream decorators, this should increase performance: 使用BufferedInputStream / BufferedOutputStream装饰器,这将提高性能:

Server Side 服务器端

BufferedOutputStream os = new BufferedOutputStream(sock.getOutputStream());

Client side 客户端

BufferedInputStream is = new BufferedInputStream(sock.getInputStream());

The raw streams are not buffered (AFAIK) so you have to add the buffering manually, if needed. 原始流未缓冲(AFAIK),因此,如果需要,您必须手动添加缓冲。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM