文件从C ++客户端传输到Java服务器

时间:2010-01-13 14:21:42

标签: java c++ sockets file-upload client-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);
            }
        }
}

3 个答案:

答案 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)

代码不完整。例如。你已经省略了文件名和文件大小的发送,以及这些值的解析。这些价值是否正确?如果不进行调查,请先确保这些值是正确的值。

相关问题