2013-04-17 5 views
0

파일 전송을위한 서버 클라이언트 응용 프로그램을 작성하려고합니다. 클라이언트는 Java로 작성되고 서버는 C++로 작성됩니다.피어에 의한 연결 재설정 : 소켓 쓰기 오류 C++ - java

불행하게도

나는 다음과 같은 오류가 있습니다

import java.io.*; 
import java.net.Socket; 


public class Proba_binar 
{ 
    public static void main(String[] args) 
    { 
     byte[] buffer = null; 
     byte[] auxByte = new byte[1000]; 
     String fileName = "1.jpg"; 
     File a_file = new File(fileName); 
     try 
     { 
      // Create a socket 
      Socket socket = new Socket("192.168.14.146", 8888); 

      BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); 

      BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 


      // Read file 
      FileInputStream fis = new FileInputStream(fileName);  
      int length = (int)a_file.length(); 
      buffer = new byte[length]; 
      fis.read(buffer); 
      fis.close(); 

      // Send file length 
      System.out.println("length = " + Integer.toString(length)); 
      out.write(Integer.toString(length) + "\n"); 
      out.flush(); 

      // Send file 
      int imageSize = buffer.length; 
      char[] auxChar = new char[1000]; 
      int nr_transf = imageSize/1000; 
      int rest_byte = imageSize % 1000; 
      System.out.println("nr_transf = " + nr_transf); 

      for(int j = 0; j < nr_transf; j++) 
      { 
       // send series of 1000 bytes 
       for(int i = 0; i < 1000; i++) 
       { 
        auxChar[i] = (char)buffer[j*1000+i]; 
        auxByte[i] = buffer[j*1000+i]; 
       } 
       out.write(auxChar); 
       out.flush(); 
      } 

      // send last bytes 
      for(int i = 0; i < rest_byte; i++) 
      { 
       auxChar[i] = (char)buffer[1000*nr_transf+i]; 
       auxByte[i] = buffer[1000*nr_transf+i]; 
      } 
      out.write(auxChar, 0, rest_byte); 
      out.flush(); 

      out.close(); 
      in.close(); 
      socket.close(); 
      System.out.println("Transfer finished!"); 
     } 
     catch(IOException e) 
     { 
      e.printStackTrace(); 
     } 
    } 
} 

그리고 서버의 코드 : 여기

java.net.SocketException: Connection reset by peer: socket write error"

내 클라이언트 코드입니다

int main(int argc , char *argv[]) 

{ 

    WSADATA wsa; 

    SOCKET s , new_socket; 

    struct sockaddr_in server , client; 

    int c, bytecount, nr_transf, rest_byte, i; 

    int recv_size, file_size; 

    char message[1000]; 

    char buffer[1000]; 
    int buffer_len = 1000; 
    FILE *f = fopen("out.jpg", "wb"); 

    printf("\nInitialising Winsock..."); 
    if (WSAStartup(MAKEWORD(2, 2),&wsa) != 0) 
    { 
     printf("Failed. Error Code : %d",WSAGetLastError()); 
     return 1; 
    } 

    printf("Initialised.\n"); 

    //Create a socket 
    if((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) 
    { 
     printf("Could not create socket : %d" , WSAGetLastError()); 
     getch(); 
     return 0; 
    } 

    printf("Socket created.\n"); 

    //Prepare the sockaddr_in structure 
    server.sin_family = AF_INET; 
    server.sin_addr.s_addr = INADDR_ANY; 
    server.sin_port = htons(8888); 

    //Bind 
    if(bind(s, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) 
    { 
     printf("Bind failed with error code : %d" , WSAGetLastError()); 
     getch(); 
     return 0; 
    } 

    puts("Bind done"); 

    //Listen to incoming connections 
    listen(s, 3); 

    //Accept and incoming connection 
    puts("Waiting for incoming connections..."); 

    c = sizeof(struct sockaddr_in); 
    new_socket = accept(s, (struct sockaddr*)&client, &c); 
    if (new_socket == INVALID_SOCKET) 
    { 
     printf("accept failed with error code : %d", WSAGetLastError()); 
     getch(); 
     return 0; 
    } 

    puts("Connection accepted"); 

    //Receive FILE DIMENSION from client 

    if((recv_size = recv(new_socket, message, 1000, 0)) == SOCKET_ERROR) 
    { 
     puts("recv failed"); 
     getch(); 
    }  
     message[recv_size] = '\0'; 
    file_size = atoi(message); 

    printf("\nfile_size = %d", file_size); 

    nr_transf = file_size/1000; 
    rest_byte = file_size % 1000; 

    //Receive FILE from client 

    for(i = 0; i < nr_transf; i++) 

    { 

     // receive 1000 bytes 

     if((bytecount = recv(new_socket, buffer, buffer_len, 0)) == SOCKET_ERROR) 

     { 

      printf("Receive failed auxChar"); 

      getch(); 

      return 0; 

     } 

     fwrite(buffer, 1, buffer_len, f); 

    } 

    // receive last bytes 

    if((bytecount = recv(new_socket, buffer, rest_byte, 0)) == SOCKET_ERROR)  

    { 

     printf("Receive failed rest_byte"); 

     getch(); 

     return 0; 

    } 

    fwrite(buffer, 1, rest_byte, f); 

    fclose(f); 

    printf("Receive finished!"); 





    closesocket(s); 

    WSACleanup(); 



    getch(); 

    return 0; 

} 

나는에 해당하는 서버를 만들어 자바와 완벽하게 작동합니다. C + + 버전의 문제점을 알 수 없습니다. 미리 감사드립니다.

답변

0

recv()는 모든 바이트 요청 읽을 것이라는 점을 보장하지 않습니다

...calling recv will return as much data as is currently available—up to the size of the buffer specified...

이것은 for/recv 루프가 잘못 구조화하고 그것이 아마 서버가 모든 데이터를 읽기 믿는 경우가 있다는 것을 의미 하지만 그렇지 않았습니다. 그 결과 클라이언트가 모든 데이터를 보내기 전에 서버가 소켓을 닫게되어 Java 클라이언트가보고 한 오류가 발생합니다. recv 루프

예 (안된) 재구성 :

int totalBytesRead = 0; 
int bytesRead; 
while (totalBytesRead < file_size) 
{ 
    if((bytesRead = recv(new_socket, buffer, buffer_len, 0)) == SOCKET_ERROR) 
    { 
     /* Handle failure. */ 
     break; 
    } 

    if (bytesRead != fwrite(buffer, 1, bytesRead, f)) 
    { 
     /* Handle failure. */ 
     break; 
    } 

    totalBytesRead += file_size; 
} 

연결 소켓이 일치 recv()들 같은 "청크에서 데이터를 읽을 수 있음을 의미하지는 않는다 mutilple send() S를 사용하여, 기초 스트림 것을 기억 "그들이 보내 졌을 때. 이미 언급 한 데이터 내용 검색 오류 외에도 파일 크기 읽기에도 똑같이 적용됩니다. 전체 파일 크기가 읽힐 것이라는 보장은 없습니다.

다른 유형의 데이터가 올바르게 읽히도록 간단한 프로토콜을 설계하는 것이 좋습니다. 예를 들어, 클라이언트는 다음을 전송합니다.

<file_size>\n<file_content>

서버는 개행 문자까지 모든 데이터를 읽고 파일 크기로 변환합니다. 그런 다음 서버는 올바른 파일 크기를 가지고 있는지를 알고 있습니다. 그런 다음 서버는 소켓에서 file_size 바이트를 읽습니다. 마지막으로 서버는 성공 또는 실패를 나타 내기 위해 응답합니다.

success\n

클라이언트는 응답을 받기 위해 줄 바꿈 문자를 읽습니다.

+0

서버 코드를 업데이트했지만 여전히 동일한 오류가 있습니다. 기본적으로 클라이언트는 'file_size'바이트를 보내고 (서버가 'file_size'정수를 포함하는 첫 번째 메시지를 수신하면 테스트 함) 서버가 임의의 바이트를 더 빨리 수신하고 소켓을 닫습니다. 마지막으로 클라이언트는 같은 오류를 발생시킵니다. "피어에 의한 연결 재설정 : 소켓 쓰기 오류 ". 나는 정말로 무슨 일이 일어나고 있는지 모르겠다 ... – adrian2012

+0

나는 내 클라이언트 코드를 다음과 같이 제거했다 : "while ((bytesReceived = input.read (buffer))> 0) { out.write (buffer, 0, bytesReceived) ; System.out.println (bytesReceived); 휴식; } "이제 완벽하게 작동합니다. 당신의 도움을 주셔서 감사합니다! – adrian2012

관련 문제