首页 文章

连接由peer重置:套接字写错误c - java

提问于
浏览
0

我正在尝试编写用于文件传输的服务器 - 客户端应用程序 . 客户端是用Java编写的,服务器是用C语言编写的 .

不幸的是我有以下错误:

java.net.SocketException:通过对等方重置连接:套接字写入错误“

这是我的客户代码:

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版本有什么问题 . 提前致谢!

1 回答

  • 0

    recv()不保证它将读取所有请求的字节:

    ...调用recv将返回当前可用的数据 - 达到指定缓冲区的大小...

    这意味着 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() 并不意味着匹配的 recv() 将读取与发送时相同的"chunks"中的数据 . 除了已经提到的数据内容检索错误之外,这同样适用于读取文件大小 . 无法保证读取整个文件大小 .

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

    <file_size> \ n <file_content>

    服务器读取所有数据直到换行符并将其转换为文件大小 . 然后服务器确定它具有正确的文件大小 . 然后,服务器从套接字读取 file_size 个字节 . 最后,服务器响应以指示成功或失败:

    成功\ n

    客户端读取换行符以获取响应 .

相关问题