Search code examples
clinuxsocketssend

C socket, send message after file, TCP


I want to send file through socket and after that i want to send three messages. This code below works, but i have to send first sentence two times. My question is why? Without one sentence1, receiver display sentence2, sentence3 and sentence3. What is wrong with this code? I'm using tcp protocol.

Sender.c

char file_size[256];
struct stat file_stat;
int sent_bytes = 0;
int fd;
int offset;
int remain_data;

fd = open(FILE_TO_SEND, O_RDONLY);
if (fd == -1)
{
        fprintf(stderr, "Error opening file --> %s", strerror(errno));

        exit(EXIT_FAILURE);
}

/* Get file stats */
if (fstat(fd, &file_stat) < 0)
{
        fprintf(stderr, "Error fstat --> %s", strerror(errno));

        exit(EXIT_FAILURE);
}

fprintf(stdout, "File Size: \n%d bytes\n", file_stat.st_size);

sprintf(file_size, "%d", file_stat.st_size);

write(sck, file_size, 256);

char buffer[1024] = "";


while (1) {
    int bytes_read = read(fd, buffer, sizeof(buffer));
    if (bytes_read == 0) 
        break;

    void *p = buffer;
    while (bytes_read > 0) {
        int bytes_written = write(sck, p, bytes_read);
        if (bytes_written <= 0) {
            // handle errors
        }
        bytes_read -= bytes_written;
        p += bytes_written;

    }
}


char sentence[1024];


write(sck, sentence1, 1024);

write(sck, sentence1, 1024);

write(sck, sentence2, 1024);

write(sck, sentence3, 1024);

Receiver.c

char buffer[1024] = "";
int sck = *((int*) arg);

int file_size;

read(sck, buffer, 256);
file_size = atoi(buffer);

ssize_t len;
FILE *received_file;
int remain_data = 0;


received_file = fopen("plik.pdf", "w");
if (received_file == NULL)
{
        fprintf(stderr, "Failed to open file foo --> %s\n", strerror(errno));

        exit(EXIT_FAILURE);
}

remain_data = file_size;

while (((len = recv(sck, buffer, 1024, 0)) > 0) && (remain_data > 0))
{
        fwrite(buffer, sizeof(char), len, received_file);
        remain_data -= len;
}
fclose(received_file);



read (sck, buffer, 1024);
printf("%s 1\n", buffer);    

read (sck, buffer, 1024);
printf("%s 2\n", buffer);

read (sck, buffer, 1024);
printf("%s 3\n", buffer);

Solution

  • Nothing to do with TCP protocol. Your logic is flawed. You are receiving the data and then checking for remain_data. So your sentence1 is received and discarded in the while loop.

    Move your recv() into the body of while to fix this or change the order in while.

    while ((remain_data > 0) && ((len = recv(sck, buffer, 1024, 0)) > 0))
    

    In the modified while, you call recv() only if remain_data > 0. recv() is not called if remain_data == 0 (lazy evaluation). So your while loop ends immediately after receiving the file and ready to receive your sentences. In your code, the while loop read the first sentence, then checked remain_data > 0 effectively discarding sentence1