0

I have been trying to transfer files over TCP\IP on a windows client to Linux server. This has been a major issue for the passed few days due to a lack of understanding why the last packet is not received on the server side, which brakes the writing of the file.

What I want to achieve is downloading images(JPG,PNG), programs (EXE) and etc`..

Output

Output from server side

Client

            lltoa(size.QuadPart,container,10);
            //Send file size
            send(sock, container, sizeof(container), 0);
            bzero(container,1024);
            //End of file size
            unsigned __int64 uiPos = 0;
            unsigned __int64 uiRemaining = ul.QuadPart;
            while (uiRemaining > 0)
            {
                ul.QuadPart = uiPos;
                ov.Offset = ul.LowPart;
                ov.OffsetHigh = ul.HighPart;
                DWORD dwNumToSend = (uiRemaining <= 3) ? 1 :1024; //(DWORD)uiRemaining;
                if (!TransmitFile(sock,get_file, dwNumToSend, 0, &ov, NULL, 0))
                {
                    if ((GetLastError() != ERROR_IO_PENDING) && (WSAGetLastError() != WSA_IO_PENDING))
                    break;
                    WaitForSingleObject(ov.hEvent, INFINITE);
                }
                uiPos += dwNumToSend;
                uiRemaining -= dwNumToSend;
                //Sleep(1);
            }
            CloseHandle(ov.hEvent);
            CloseHandle(get_file);  

Server

            file_size = atoi(response);
            printf("File size: %lli \n",file_size);
            bzero(response,18384);
            //End of file size
            
            //First packet of file
            
            len = recv(client_socket,response,sizeof(response)<file_size?(sizeof(response)):file_size,MSG_WAITALL);
            printf("Received: %i \n",len);
            if (len == 0)
            {
                printf("Error downloading file!");
                goto jump;
            }

            file_size = file_size - len;
            int counter = 0;
            while(file_size > 0)
            {
            //Start getting the file
                fwrite(response,1,len,new_file);
                bzero(response,18384);
                len = recv(client_socket,response,((file_size <= 1024) || (len < 1024))?file_size:sizeof(response),MSG_WAITALL);
                printf("Received: %i\t|",len);
                if(len <= 0)
                {
                    break;
                }
                //Check if this is the last packet
                
                file_size = file_size - len;
                printf("Response #%i\tbytes_received: %i\tbytes remain:%li \n",counter,len,file_size);
                counter += 1;
            }
            if(file_size > 0)
            {
                printf("\t\t\tError downloading file!  bytes left:%li \n",file_size);
                
            }
            else
            {
                printf("Successfully downloaded file! \n");
            }
            fclose(new_file);
            goto jump;

With error handeling for recv():

enter image description here If more of the server side code is needed please comment.. I think that this will do though..

Thank You!!

Community
  • 1
  • 1
TomP
  • 67
  • 1
  • 6
  • Please provide also error code from errno when recv returned -1, you can print errno or you can use perror. – raliscenda May 05 '20 at 12:38
  • that just means that there was no more data to receive from the socket... thats why recv() returned -1.. @raliscenda – TomP May 05 '20 at 12:55
  • but recv can return more types of error and specific details may help debugging your issue. @Pch12_ – raliscenda May 05 '20 at 12:59
  • ill check that out. ill post in a few minutes – TomP May 05 '20 at 13:07
  • Error : Resource temporarily unavailable. Thats what it prints @raliscenda – TomP May 05 '20 at 13:17
  • OK, EAGAIN on MSG_WAITALL means there really are no data. This flag can be ignored hovever, depending on configuration of your socket. I would look in to computation of remaining size or check whit what value is recv called. Otherwise test with netcat acting as client and or server. @Pch12_ – raliscenda May 05 '20 at 14:00
  • My socket is configured with a timeout . @raliscenda – TomP May 05 '20 at 15:30

1 Answers1

1

Based on code you have showed, found some problems. After edited as below it works for me. You can have a try. (Please show ul.QuadPart, ul.LowPart and ul.HighPart related code if you still have issues.)

At client side:

Change DWORD dwNumToSend = (uiRemaining <= 3) ? 1 :1024; to DWORD dwNumToSend = (uiRemaining <= 1024) ? uiRemaining : 1024;

At server side:

Change ((file_size <= 1024) || (len < 1024))?file_size:sizeof(response) to (file_size <= sizeof(response))?file_size:sizeof(response)

Rita Han
  • 9,574
  • 1
  • 11
  • 24