简体   繁体   中英

TCP server doesn't receive the right bytes number from client

I'm doing a little project of TCP connection by C language, and the problem with my code is mentioned in the title. And the following is the uploading part of my code

Client Side:

        FILE * fp = fopen(f2d, "rb+");
                    if(fp == NULL) perror("Fail to upload(client)");
                    else
                    {
                            fseek(fp, 0, SEEK_END);
                            int filesize = ftell(fp);
                            memset(buf, '\0', MAX_SIZE);
                            sprintf(buf, "%d", filesize);
                            send(serverSocket, buf, strlen(buf), 0); //send the filesize to the server
                            rewind(fp);
                            int byteNum = 0, z = 0;
                            printf("Uploading......\n");
                            while((z += byteNum) < filesize)
                            {
                                    memset(buf, '\0', MAX_SIZE);
                                    byteNum = fread(&buf, sizeof(char), sizeof(buf), fp);
                                    printf("Bytes read to buf : %d\n", byteNum);
                                    send(serverSocket, buf, sizeof(buf), 0);          
                                    printf("Totally sent bytes: %d\n", z);
                            }
                            printf("Upload completed.\n");
                    }
                    fclose(fp);

Server Side:

        printf("Upload Requested.\n");
                    f2df = fopen(buf + 4, "wb+");
                    if(f2df == NULL) perror("Fail to upload(server)");
                    else
                    {
                            memset(buf, 0, MAX_SIZE);
                            recv(clientSocket, buf, sizeof(buf), 0); //receive the filesize
                            int filesize = atoi(buf);

                            int recvNum = 0, recv_Num = 0;
                            while((recvNum += recv_Num) < filesize)
                            {
                                    memset(buf, 0, MAX_SIZE);
                                    recv_Num = recv(clientSocket, buf, sizeof(buf), 0);
                                    fwrite(&buf, sizeof(char), sizeof(buf), f2df);
                                    printf("Bytes received from recv: %d\n", recv_Num);
                                    printf("Totally received bytes: %d\n", recvNum);
                            }
                            printf("Upload completed.\n");
                    }
                    fclose(f2df);

The idea of my code is to send and receive the bytes until it reaches the filesize. But with a very high frequency(well, sometimes it functions normally, all bytes are transferred to the server) that the server seems to miss some bytes sent from the client(and the return value of "recv" function will then be zero after the client has sent all the bytes to the server, which makes the terminating condition of the while loop never be reached), which then causes an infinitive loop on the server side. PS all the other functions are without problems(eg sending and receiving filesize, the actual number of the filesize... etc), I had tested them all. And there's also no problem on the client side.

And the following is the screenshot of the problem

在此处输入图片说明

So can anyone help me out with that, I've been trying to deal with this for weeks, thanks a lot in advance!

Go through you entire client and server code and fix:

1) All those times where you do not handle correctly the results returned from system calls. This especially applies to the result returned by recv() which can be negative, (error), zero, (peer closed the connection), or some positive number less than, or equal to, the number of bytes requested - the ONLY WAY YOU CAN TELL FOR SURE HOW MANY BYTES HAVE BEEN READ IN TO THE BUFFER. Forget the number of bytes requested in the call and any memset/bzero before, and/or strlen/whatever after, it returns, they are all inadequate/misleading.

2) All those times where you assume that, just because you request the recv() of X bytes and recv() returns a positive number, that number will be X.

3) All those times that you call any str* C-style library calls on any buffers that are not 100% guaranteed to be NULL-terminated.

The main problem is the (not) handling of the send() return value, because even in the absence of any error condition, send() may return a smaller value than requested (eg if a buffer is full). After each loop cycle in the client, you increment z by the number of bytes read to buf , but disregard that a smaller number of bytes may have been sent. This leads to the outcome that the client loop completes without having sent all data, despite of incorrectly saying so. Change that eg to:

                            printf("Uploading......\n");
                            while (z < filesize)
                            {
                                    byteNum = fread(buf, sizeof(char), sizeof buf, fp);
                                    printf("Bytes read to buf : %d\n", byteNum);
                                    int sent = 0;
                                    while (byteNum > 0)
                                    {
                                        int ret = send(serverSocket, buf+sent, byteNum, 0);
                                        if (ret < 0) { perror("send"); goto fail; }
                                        sent += ret, byteNum -= ret;
                                        printf("Totally sent bytes: %d\n", z += ret);
                                    }
                            }
                            printf("Upload completed.\n");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM