编辑:
我更改了代码,以便在传输后检查文件的完整性。
但是现在当我在dos.write(buffer, 0, count)
的客户端放置一个断点,终止服务器,然后恢复客户端代码执行时,它会无限期地挂起serverMD5[i] = dataInputStream.readByte()
。
即使用户现在知道传输不成功(应用程序挂起并需要重新启动),再次这不是我预期的做(抛出IOException)。
更改过代码的原帖:
我创建了一个使用SSLSocket连接到服务器并发送一些数据的android客户端。 这是相关的客户端和服务器代码
客户端:
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是设备号)文件。
这是一个很大的问题,因为用户可能认为数据已成功传输并从设备中删除(由于应用程序的性质,发送的数据会在某些时候被删除)。
由于我设法产生了这个bug,我认为它可能会在现实场景中发生。这是我第一次使用套接字,我不知道如何解决这个问题。
此外,如果有人注意到此代码块可能出错的任何其他情况(结果不符合预期但未抛出异常的另一种情况),请告诉我。
答案 0 :(得分:1)
这是TCP的正常操作。抛开SSL,您的发送将缓冲在套接字发送缓冲区中,并在.userWrap {
position: relative;
display: inline-block;
width: 300px;
height: 50px;
overflow: visible;
z-index: 1;
}
.userWrap:hover {
z-index: 2;
}
.user {
position: absolute;
display: inline-block;
width: 300px;
height: 50px;
margin-bottom: 5px;
background: #fff;
transition: width 0.3s, height 0.3s;
}
.user:hover {
width: 350px;
height: 200px;
background: #eee;
transition: width 0.3s ease 0.5s, height 0.3s ease 0.5s;
}
.user img {
float: left;
}
.user .name, .skills {
margin-left: 5px;
}
.user .name {
font-size: 21px;
font-weight: bold;
}
函数返回后异步传输。因此send()
函数不可能立即检测到对等中断。如果您继续发送,则TCP的重试将最终失败并导致后续发送失败,对于具有send()
的Java。
IOException: connection reset
您不能假设inputStream.read(deviceIDbuffer);
填充缓冲区。你应该在这里使用read()
。
答案 1 :(得分:-1)
看起来您需要在客户端和服务器之间进行双向通信。当客户端完成上传后,您可以让客户端发送传输结束(ascii 0x4)字符(或您的客户端/服务器认为是“特殊”序列的任何其他字符)。当服务器收到转换结束字符时,服务器可以回复它获得的字节数。在客户端,等待响应,如果达到超时,告诉用户出现了问题。