我有一个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);
}
}
}
答案 0 :(得分:0)
发送套接字是在文件末尾关闭,还是在同一个套接字上流传输的下一个文件?如果流式传输多个文件,如果recvHeader()
中文件大小的结束性错误,则可以从下一个文件中获取数据,即发送长度为0x0102的文件并尝试读取长度为0x0201的文件
其他问题,为什么要为第一次读取提供最大值,但不能为同一文件中的以下读取提供最大值?
答案 1 :(得分:0)
我看到的一个问题是,您认为如果发送返回非错误,它会发送您请求它发送的整个块。这不一定是真的,特别是对于流套接字。你发送的数据包有多大,有多少?最可能发生这种情况的原因是,如果套接字的sndbuf已填满,并且套接字_sd设置为非阻塞。我不是肯定的(取决于堆栈实现),但我相信如果你的连接的TCP传输窗口已满,它也可能发生,并且tcp无法将整个数据包排入队列。
你应该循环发送直到发送最大值。
所以:
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
}
}
答案 2 :(得分:0)
代码不完整。例如。你已经省略了文件名和文件大小的发送,以及这些值的解析。这些价值是否正确?如果不进行调查,请先确保这些值是正确的值。