gpt4 book ai didi

java - 如果服务器在写入 OutputStream 时关闭,SSLSocket 客户端不会抛出异常

转载 作者:太空宇宙 更新时间:2023-11-03 14:49:49 24 4
gpt4 key购买 nike

编辑:

我已经更改了代码,以便在传输后检查文件的完整性。

但是现在当我在客户端的 dos.write(buffer, 0, count) 下断点,杀死服务器,然后恢复客户端代码执行时,它卡在 serverMD5 [i] = dataInputStream.readByte() 无限期。

即使用户现在知道传输不成功(应用程序挂起并需要重新启动),这还是没有按照我的预期进行(抛出 IOException)。

原始帖子更改代码:

我创建了一个 android 客户端,它使用 SSLSocket 连接到服务器并发送一些数据。下面是相关的客户端和服务端代码

客户:

try {
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket();
sslsocket.connect(new InetSocketAddress(SERVER_IP, UPLOAD_PORT), 2000);

OutputStream outputStream = sslsocket.getOutputStream();

DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
dataOutputStream.writeInt(DEVICE_ID);
dataOutputStream.writeLong(FILE_LENGTH);

MessageDigest md = MessageDigest.getInstance("MD5");
DigestOutputStream dos = new DigestOutputStream(outputStream, md);

InputStream readingsInputStream = new FileInputStream(FILE_NAME);

int count;
byte[] buffer = new byte[10 * 1024];
while ((count = readingsInputStream.read(buffer)) > 0) {
dos.write(buffer, 0, count);
}
readingsInputStream.close();

byte[] md5 = md.digest();
byte[] serverMD5 = new byte[16];

DataInputStream dataInputStream = new DataInputStream(sslsocket.getInputStream());

for (int i = 0;i<16;i++) {
serverMD5[i] = dataInputStream.readByte();
if (md5[i] != serverMD5[i]) throw new Exception("MD5 mismatch");
}

sslsocket.close();
} catch (Exception e) {
...
}

服务器:

try {
SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();

InputStream inputStream = sslSocket.getInputStream();

DataInputStream dataInputStream = new DataInputStream(inputStream);
int deviceID = dataInputStream.readInt();
long fileLength = dataInputStream.readLong();

MessageDigest md = MessageDigest.getInstance("MD5");
DigestInputStream dis = new DigestInputStream(inputStream, md);

OutputStream readingsOutputStream = new FileOutputStream("Device"+deviceID+".txt", false);

int count;
byte[] buffer = new byte[1];
do {
count = dis.read(buffer);
readingsOutputStream.write(buffer, 0, count);
fileLength -= count;
} while (fileLength > 0);

readingsOutputStream.close();

byte[] md5 = md.digest();

DataOutputStream md5OutputStream = new DataOutputStream(sslSocket.getOutputStream());
for (int i = 0;i<16;i++) md5OutputStream.writeByte(md5[i]);

sslSocket.close();
} catch (Exception e) {
...
}

通常这一切都按预期工作但是当我在客户端的 dos.write(buffer, 0, count) 行放置断点然后在到达断点时终止服务器时出现问题.

在客户端继续执行代码后,它没有抛出异常,只是遍历此代码块的其余部分,让我相信文件已成功写入服务器。

当然情况并非如此,因为在写入 OutputStream 之前服务器已关闭。这会导致服务器上出现空的 DeviceX.txt(X 是设备编号)文件。

这是一个大问题,因为用户可能认为数据已成功传输并将其从设备中删除(由于应用程序的性质,发送的数据会在某个时间点被删除)。

由于我设法产生了这个错误,我认为它也有可能在现实世界中发生。这是我第一次使用套接字,我不知道如何解决这个问题。

此外,如果有人注意到此代码块可能出现的任何其他问题(结果不符合预期但未抛出异常的另一种情况),请告诉我。

最佳答案

这是TCP的正常操作。撇开 SSL,您的发送被缓冲在套接字发送缓冲区中,并在 send() 之后异步传输。函数已经返回。因此,send() 是不可能的立即检测对等中断的功能。如果您继续发送,TCP 对未决数据的重试最终将失败并导致后续 发送失败,在 Java 的情况下为 IOException: connection reset .

inputStream.read(deviceIDbuffer);

你不能假设 read()填充缓冲区。你应该使用 DataInputStream.readInt()在这里。

关于java - 如果服务器在写入 OutputStream 时关闭,SSLSocket 客户端不会抛出异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35470566/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com