1

我有一个这样的 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();

一个问题是:为什么循环不会在文件末尾停止?第二个问题是,为什么也这么慢?

4

2 回答 2

4

它不会停止,因为

if (i == 1) {

在您的服务器源中应该是

if (i == -1) {

或者,如果您想真正安全:

if (i <= 0) {

此外,您可能会因以下行导致数据损坏:

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

您应该将其更改为:

os.write(mybytearray, 0, i);

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

于 2010-12-08T08:00:34.187 回答
2

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

服务器端

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

客户端

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

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

于 2010-12-08T08:01:02.747 回答