1

Modify the following socket program and let the server send a file to the client.

I'm stuck with this i can't figure this out. below is the server and client that where given to me. right now the server will send the client the time stamp.

Socket Server Example (server.c)

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>

int main(int argc, char *argv[])
{
    int listenfd = 0, connfd = 0;
    struct sockaddr_in serv_addr;

    char sendBuff[1025];
    time_t ticks;

    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    memset(&serv_addr, '0', sizeof(serv_addr));
    memset(sendBuff, '0', sizeof(sendBuff));

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port = htons(5000);

    bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

    listen(listenfd, 10);

    while(1)
    {
        connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);

        ticks = time(NULL);
        snprintf(sendBuff, sizeof(sendBuff), "%.24s\r\n", 
     ctime(&ticks));
        write(connfd, sendBuff, strlen(sendBuff));

        close(connfd);
        sleep(1);
     }
 }

Socket Client Example (client.c)

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])
{
    int sockfd = 0, n = 0;
    char recvBuff[1024];
    struct sockaddr_in serv_addr;

    if(argc != 2)
    {
        printf("\n Usage: %s <ip of server> \n",argv[0]);
        return 1;
    }

    memset(recvBuff, '0',sizeof(recvBuff));
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("\n Error : Could not create socket \n");
        return 1;
    }

    memset(&serv_addr, '0', sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(5000);

    if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr)<=0)
    {
        printf("\n inet_pton error occured\n");
        return 1;
    }

    if( connect(sockfd, (struct sockaddr *)&serv_addr, 
    sizeof(serv_addr)) < 0)
    {
       printf("\n Error : Connect Failed \n");
       return 1;
    }

    while ( (n = read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0)
    {
        recvBuff[n] = 0;
        if(fputs(recvBuff, stdout) == EOF)
        {
            printf("\n Error : Fputs error\n");
        }
    }

    if(n < 0)
    {
        printf("\n Read error \n");
    }

    return 0;
} 
1
  • What "can't you figure out"? What have you tried? Commented Oct 8, 2018 at 4:56

2 Answers 2

1

If you don't want to or can't read the whole content of the file you wish to send at once into memory, use a loop with your buffer:

    #include <fcntl.h>
    if (argv[1])    // or whereever you get the file name from
    {
        int fd = open(argv[1], O_RDONLY);
        if (fd < 0) perror(argv[1]);
        else
        {
            ssize_t n;
            while (n = read(fd, sendBuff, sizeof sendBuff), n > 0)
                if (send(connfd, sendBuff, n, MSG_NOSIGNAL) < 0)
                { perror("send"); break; }
            close(fd);
            if (n < 0) perror("read");
        }
    }

In the client use a similar loop. Be aware that the file might contain NUL characters, so functions like fputs, operating on C strings, are inept.

    while ((n = read(sockfd, recvBuff, sizeof recvBuff)) > 0)
        if (write(1, recvBuff, n) < 0) perror("write");
Sign up to request clarification or add additional context in comments.

4 Comments

how does the client know its reached the end?
@pm100 - By evaluating the above condition read(…) > 0 does the client know it reached the end. Be aware that in the program at hand the socket is in blocking mode.
the read will simply block while waiting for data to arrive. What do you do now? Do you timeout? How long should you wait? You must send the file length first to indicate to the receiver how much data to receive. Dont be fooled into thinking that if you send one block you will receive one block. TCP has no concept of blocks or recoirds, only streams of bytes
@pm100 - What you state is partly well-known and partly wrong. Your questions are waste. Do you timeout? There is not a bit of timeout in the OP's code or in my supplement. How long should you wait? The client code unequivocally shows how long it waits - in each loop cycle until read() returns, and overall until read() returns a non-positive value. We need not send the file length first to indicate to the receiver how much data to receive, since the server closes the connection after sending the file, and then the client read() returns 0.
0

Read the content of the file you wish to send, and save it into a string:

char *loadFileContent(char *fileName, size_t *len){
    FILE* input_file               = fopen(fileName, "rb");
    size_t stat;
    if(!input_file){
        OCSP_ERR_INDEX = OCSP_LOG_ERR_load_file_fail;
        return NULL;
    }
    fseek(input_file, 0, SEEK_END);
    long int input_file_size       = ftell(input_file);
    rewind(input_file);
    char *file_contents            = malloc((input_file_size + 1) * (sizeof(char)));
    stat = fread(file_contents, sizeof(char), (size_t) input_file_size, input_file);
    if(stat<1){
        OCSP_ERR_INDEX = OCSP_LOG_ERR_load_file_fail;
        return NULL;
    }
    fclose(input_file);
    file_contents[input_file_size] = 0;
    *len                           = (size_t) input_file_size;
    return file_contents;
}

In your code, modify the line in server that is supposed to send response to client. So this line write(connfd, sendBuff, strlen(sendBuff)); becomes:

size_t len;
char *text = loadFileContent("myfile.txt", &len);
write(connfd, text, len);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.