2015-01-08 69 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()以防止嘗試執行永遠無法阻止的讀取。