2013-04-17 110 views
0

我正在尝试编写一个用于文件传输的服务器 - 客户端应用程序。客户端用Java编写,服务器用C++编写。通过peer重置连接:套接字写入错误C++ - java

不幸的是,我有以下错误:

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

这里是我的客户端代码:

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(); 
     } 
    } 
} 

而对于服务器的代码:

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; 

} 

我在做相当于服务器Java和完美的作品。 我不知道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; 
} 

记住连接的套接字是基于数据流,使用mutilple send() s不意味着匹配recv()旨意在相同的“组块读出的数据“因为他们被送去了。除了已经提到的数据内容检索错误之外,这同样适用于读取文件大小。无法保证读取整个文件大小。

我会建议设计一个简单的协议,以确保正确读取不同类型的数据。例如,客户端发送:

<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); break; } “我现在完美地工作。谢谢你的帮助! – adrian2012

相关问题