2015-01-08 68 views
-1

我正在通过套接字创建文件传输。我的客户端使用Java,而我的服务器使用C语言。我能够确认客户端和服务器之间的连接,并将文件名也发送到服务器。该文件也在服务器端创建,但服务器无法获取EOF,因此陷入循环。因此,文件传输后没有数据传输。下面是我的相关客户端和服务器代码。请指导/纠正我如何实现这一点。文件传输后没有输入传输 - 套接字

服务器用C

int connfd; 
    int n; 
    char buffer[3000]; 
    FILE *fp; 
    int result; 
    char *message = ""; 

    n = recv(connfd, buffer, sizeof buffer, 0); //connfd is my created socket 

    if (n > 0) 
    { 
     fprintf(stdout,"Received %d bytes\n", n); 
     fprintf(stdout,"Received Data: %s",buffer); 
     buffer[strlen(buffer)-1] = '\0'; 

     if(strcmp(buffer, "incoming_file")) 
     { 
      fprintf(stdout, "client: incoming file"); 
      message="send data\n"; 
      result = send(connfd , message , strlen(message) , 0); 

      if(result == SOCKET_ERROR) 
       printf("send failed with error codfe %d\n",WSAGetLastError()); 

      else 
       fprintf(stdout,"\nsent %d bytes out of %u \n",result,strlen(message)); 

     } 

     else 
     { 
      fprintf(stdout,"invalid data received"); 
      return NULL; 
     } 

     n = recv(connfd, buffer, sizeof buffer, 0); 

     if(n > 0) 
     { 
      fprintf(stdout, "Received %d bytes\n", n); 
      fprintf(stdout,"Received Data: %s",buffer); 

      fp = fopen(buffer, "wb"); 

      if (fp == NULL) 
      { 
       printf("File not created!\n"); 
       return NULL; 
      } 
      else 
      { 
       printf("Created file %s\n", buffer); 

       message="file created\n"; 
       result = send(connfd , message , strlen(message) , 0); 

       if(result == SOCKET_ERROR) 
        printf("send failed with error codfe %d\n",WSAGetLastError()); 
       else 
        fprintf(stdout,"\nsent %d bytes out of %u \n",result,strlen(message)); 

       while ((n = recv(connfd, buffer, sizeof buffer, 0)) > 0) 
       { 
        fwrite(buffer, sizeof(char), n, fp); 
        fprintf(stdout, "Received %d bytes\n", n); 
       } //gets stuck in this loop 

       printf("\n after while"); // control never comes here 

       message="file uploaded\n"; 
       result = send(connfd , message , strlen(message) , 0); 

       if(result == SOCKET_ERROR) 
        printf("send failed with error codfe %d\n",WSAGetLastError()); 
       else 
        fprintf(stdout,"\nsent %d bytes out of %u \n",result,strlen(message)); 
      } 
     } 

     else 
     { 
      fprintf(stdout,"filename not received"); 
     } 
    } 

    else 
    { 
     fprintf(stdout,"no data received"); 
    } 

    printf("client disconnected from); 
    getchar(); 
    closesocket(connfd); 
    WSACleanup(); 
    return 0; 
} 

客户端在Java中

  File file = new File("C:/Data/.../Picture1.jpg"); 
      byte[] bytes = new byte[3000]; 
      FileInputStream fis = new FileInputStream(file); 
      BufferedInputStream bis = new BufferedInputStream(fis); 
      BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
      OutputStream out = socket.getOutputStream(); 

      int count; 
      out.write(("incoming_file"+"\0").getBytes(Charset.forName("UTF-8"))); 

      String st; 
      int i = 0; 
      while((st = input.readLine()) != null) 
      { 
       switch (st) 
       { 
       case "send data": 
        System.out.println("data: "+st); 
        System.out.println("File name: "+file.getName().trim()); 
        out.write((file.getName()+"\0").getBytes("UTF-8")); 
        out.flush(); 

        break; 

       case "file created": 
        System.out.println("data: "+st); 

        while ((count = bis.read(bytes)) > 0) 
        { 
         System.out.println(count); 
         out.write(bytes, 0, count); 
        } 

        out.flush(); 
        fis.close(); 
        bis.close(); 

        System.out.println("file sending complete"); //this gets printed 

        break; 

       case "file uploaded": //never comes here 
        System.out.println("data: "+st); 
        break; 

       default: 
         System.out.println("in default: "+st); 
         break; 
       } 
       System.out.println(i++); 
      } 

      out.flush(); 
      out.close(); 
      input.close(); 
     } 

     catch(IOException ioe) 
     { 
      System.out.println("Exception during communication. Server closed connection."); 
      ioe.printStackTrace(); 
     } 

     finally 
     { 
      try 
      { 
       // Close the socket before quitting 
       socket.close(); 
      } 
      catch(Exception e) 
      { 
       e.printStackTrace(); 
      }     
} 

回答

0
this line from the man page for recv() contains the answer: 

" If no messages are available at the socket, the receive calls wait for 
    a message to arrive," 

a MUCH better method is to code a select() (with timeout)/recv() loop. 

Then when a timeout occurs, the file transfer is completed. 
remember to refresh time timeout value each time through the loop. 
use a reasonable timeout, say 1 second, to allow for 
network and similar delays. 

I.E. 
while(forever) 
    // refresh timeout value 
    // result = select(...) 
    // note: result value: 0 == timeout, <0 == error, >0 == data received 
    // if 0 < result 
    // then, recv() 
    // else exit loop 
end while 
// if 0==result 
// then all ok 
// else if 0 > result 
// then handle error 
// endif 
+1

这不是OP问题的答案。这是一个重新设计。 –

0

你需要一个更复杂的协议。一般来说,通常不可能被动地确定远程机器何时关闭连接或停止传输数据。

解决传输结束问题的一种方法是让客户端在文件本身之前发送文件大小 - 然后当服务器接收到很多字节时就知道它包含整个文件。另一种方法是将文件以可识别边界的格式打包,例如MIME或SOAP信封。

即便如此,客户端可能会失败或断开传输中断,因此对于强大的服务器,您将希望使用带有超时的select()以防止尝试执行永远无法阻止的读取。