![](/img/trans.png)
[英]Java: Transfer a file from server to client and from client to server
[英]File transfer from C++ client to Java server
我有一个C ++客户端,需要将文件发送到C ++服务器。 我将文件拆分为PACKET_SIZE(= 1024)个字节,并通过TCP套接字发送它们。 在服务器端,我最多将PACKET_SIZE个字节读到缓冲区。 当客户端发送的文件小于PACKET_SIZE时,服务器接收的字节数大于发送的字节数。 即使我将字节数限制为恰好是文件的大小,文件也有所不同。 我知道问题与客户端无关,因为我已经使用c ++服务器对其进行了测试,并且可以完美地工作。
谢谢。
服务器:
public void run() {
DataInputStream input = null;
PrintWriter output = null;
try {
input = new DataInputStream (_client.getInputStream());
}
catch (Exception e) {/* Error handling code */}
FileHeader fh = recvHeader(input);
size = fh._size;
filename = fh._name;
try {
output = new PrintWriter(_client.getOutputStream(), true);
}
catch (Exception e) {/* Error handling code */}
output.write(HEADER_ACK);
output.flush();
FileOutputStream file = null;
try {
file = new FileOutputStream(filename);
}
catch (FileNotFoundException fnfe) {/* Error handling code */}
int total_bytes_rcvd = 0, bytes_rcvd = 0, packets_rcvd = 0;
byte [] buf = new byte [PACKET_DATA_SIZE];
try {
int max = (size > PACKET_DATA_SIZE)? PACKET_DATA_SIZE: size;
bytes_rcvd = input.read(buf,0, max);
while (total_bytes_rcvd < size) {
if (-1 == bytes_rcvd) {...}
++packets_rcvd;
total_bytes_rcvd += bytes_rcvd;
file.write (buf,0, bytes_rcvd);
if (total_bytes_rcvd < size)
bytes_rcvd = input.read(buf);
}
file.close();
}
catch (Exception e) {/* Error handling code */}
}
客户:
char packet [PACKET_SIZE] ;
file.open (filename, ios::in | ios::binary);//fopen (file_path , "rb");
int max = 0;
if (file.is_open()) {
if (size > PACKET_SIZE)
max = PACKET_SIZE;
else
max = size;
file.read (packet , max);
}
else {...}
int sent_packets = 0;
while (sent_packets < (int) ceil (((float)size)/PACKET_SIZE) ) {
_write=send(_sd , packet, max,0);
if (_write <0) {...}
else {
++sent_packets;
if (size > PACKET_SIZE* sent_packets) {
if (size - PACKET_SIZE* sent_packets >= PACKET_SIZE)
max = PACKET_SIZE;
else
max = size - PACKET_SIZE* sent_packets;
file.read (packet , max);
}
}
}
发送套接字是在文件末尾关闭还是下一个文件通过同一套接字流传输? 如果流传输了多个文件,并且如果recvHeader()
的文件大小的recvHeader()
有误,则可以从下一个文件中提取数据,即,发送一个长度为0x0102的文件并尝试读取一个长度为0x0201的文件。
另一个问题,为什么您要为同一文件的第一次读取提供最大值,而不为随后的读取提供最大值?
我看到的一个问题是,似乎您假设如果发送返回一个非错误,那么它将发送您请求发送的整个块。 这不一定是正确的,尤其是对于流套接字。 您要发送的数据包有多少,有多少? 发生这种情况的最可能原因是套接字的sndbuf已填充,并且套接字_sd设置为非阻塞。 我不是很乐观(取决于堆栈的实现),但是我认为如果TCP传输窗口已满,并且连接到TCP不能使整个数据包入队,也有可能发生这种情况。
在发送max之前,您可能应该循环发送。
因此:
int send_ct=0;
while( (_write = send(_sd, packet + send_ct, max-send_ct, 0)) > 0) {
send_ct += _write;
if(send_ct >= max) {
break;
} else {
// Had to do another send
}
}
代码不完整。 例如,您省略了文件名和文件大小的发送以及这些值的解析。 这些值正确吗? 如果不是这样,请在进一步研究之前先确保这些值是正确的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.