LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   "File transfer through Socket Programming in C" (https://www.linuxquestions.org/questions/programming-9/file-transfer-through-socket-programming-in-c-4175417301/)

jack.sully 07-17-2012 09:06 PM

"File transfer through Socket Programming in C"
 
Hi,
I am using following code for file transfer throuch socket programming in C.
Separately when i am running server and client code, everything is fine.
i.e (server.c and client.c)
But when i try to include the code for server and client in a single code by calling self defined function. It's not working
An empty file of zero bytes in being created.

Here is the code.

/* client_server_function_test.c*/

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>

#define PORT 2200
void Socket_server();
void Socket_client();

main()
{
puts("Server called");
Socket_server();
//Socket_client();
return(0);
}

void Socket_server()
{
int sock1,sock2,clength,s;
sock1 = socket(AF_INET,SOCK_STREAM,0);
// printf("%d\n",sock1);
struct sockaddr_in serv,cli;
puts("Trying Connection");
serv.sin_family = AF_INET;
serv.sin_port = htons(PORT);
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
bind(sock1,(struct sockaddr *)&serv, sizeof(serv));
listen(sock1,5);
clength = sizeof(cli);
char buf[50];
puts("Trying again");
Socket_client();
sock2 = accept(sock1,(struct sockaddr *)&cli,&clength);
printf("\n Client Connected\n");
FILE* fp = fopen("1342181561","r");
while(!feof(fp)){
// bzero(buf,sizeof(buf));
fread(buf,sizeof(char),50,fp);
printf("%s",buf);
write(sock2,buf,50);
puts("Trying to write");
}
write(sock2,"quit1234",50);
fclose(fp);
}

void Socket_client()

{
int sock3;
sock3 = socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in serv;

serv.sin_port = htons(PORT);
printf("%x %x\n",PORT,htons(PORT));
serv.sin_family = AF_INET;
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
printf("client connecting\n");
connect(sock3, (struct sockaddr *)&serv,sizeof(serv));
// return(sock3);
puts("Connected");
char buf[50];

FILE* fp1 = fopen("client_new.txt","w");
// return(sock3);
while(1)
{
puts("File opened for writing");
// bzero(buf,sizeof(buf));
read(sock3,buf,50);
puts("Start writing");
if(strcmp(buf,"quit1234")==0)
{
break;
}
}
fprintf(fp1,"%s",buf);
}
//return(sock1);
fclose(fp1);
}

Here's the output:

surendra@ubuntu:~/Linuxcodes/File_handling$ gcc client_server_function_test.c
surendra@ubuntu:~/Linuxcodes/File_handling$ ./a.out
Server called
Trying Connection
Trying again
898 9808
client connecting
Connected
File opened for writing
/File_handling$ ls -lrt

-rw-r--r-- 1 0 2012-07-17 21:57 client_new.txt

Any suggestions.

cliffordw 07-18-2012 12:45 AM

Hi there,

It's hard to tell where things are going wrong as you don't seem to be checking the return codes from your function calls. I'd strongly recommend that you check the return codes of all function calls (like bind, listen, connect, accept, write, read, etc), and handle any errors appropriately.

I think a large part of the problem is that this code is single threaded. For the client and server to work, they each need a turn to do a bit of work, i.e. the server sends 50 bytes, the client reads them, then the server gets a turn again to send the next 50 bytes. In your code this can't happen - your server is opening the socket, then calling the client and waiting for it to finish, before trying to accept the connection and send the data. The code is most likely stuck at the read() in Socket_client(), as the connection hasn't been accept()ed, and there is no data to read.

Is there a specific reason you want both the server and client in a single program?

Good luck!

jack.sully 07-18-2012 06:43 AM

"File transfer through Socket Programming in C"
 
I am implementing an application to send messagea with in an Intranet.
So far i have created a file with current timestamp that holds the message

I have transferred the message locally within the system by writing and running separate for codes for client and server.

But now i want entire application within a single program. So , i was trying to call server and client through user defined function.
Is it possible. Can u help me with code or any useful link.


Thanks

dwhitney67 07-18-2012 06:55 AM

Quote:

Originally Posted by jack.sully (Post 4731551)
Is it possible. Can u help me with code or any useful link.

Consider using fork() to spawn a separate process for the client. For example (and this is very crude):
Code:

...
#include <unistd.h>

int main()
{
    if (fork() == 0)
    {
        sleep(1);    /* give time for the server to start */

        Socket_client();
    }
    else
    {
        Socket_server();
    }

    return 0;
}


piyush.sharma 07-18-2012 07:06 AM

just try to print the return value of read() & write() functions, it will help to check whether some text has been processed or not.

jack.sully 07-18-2012 07:09 AM

I have edited the code but it's still the same ,it's creating the file but unable to write into it.

ubuntu:~/Linuxcodes/File_handling$ ./a.out
Trying Connection
Trying again
898 9808
client connecting
Connected
File opened for writing
898 9808
client connecting
Connected
File opened for writing
^C

@ubuntu:~/Linuxcodes/File_handling$ ls -lrt
-rw-r--r-- 1 0 2012-07-18 08:06 client_new.txt

piyush.sharma 07-18-2012 08:20 AM

Its good if you consider handling error codes, You are getting stuck in something before you read/write, but your printed output is unable to express where the problem is.

dwhitney67 07-18-2012 08:21 AM

Quote:

Originally Posted by jack.sully (Post 4731574)
I have edited the code but it's still the same...

You can edit all day long, but if you fail to heed the advice given earlier (with regards to performing error checking), your code is destined to fail.

Here's a functional "copy" of your code; note that there are still areas which are still not "safe" from errors. I'll leave it as an exercise for you to find these areas.

Code:

/* client_server_function_test.c*/

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>

#include <string.h>
#include <unistd.h>
#include <errno.h>

#define PORT 2200
void Socket_server();
void Socket_client();

int main()
{
    if (fork() == 0)
    {
        sleep(1);
        Socket_client();
    }
    else
    {
        Socket_server();
    }

    return 0;
}

void Socket_server()
{
    int sock1 = socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in serv;
    memset(&serv, 0, sizeof(serv));
    serv.sin_family      = AF_INET;
    serv.sin_port        = htons(PORT);
    serv.sin_addr.s_addr = htonl(INADDR_ANY);

    int val = 1;
    setsockopt(sock1, SOL_SOCKET, SO_REUSEADDR, (const void*) &val, sizeof(val));

    if (bind(sock1, (struct sockaddr*) &serv, sizeof(serv)) != 0)
    {
        perror("bind() failed.");
        return;
    }

    if (listen(sock1, 5) != 0)
    {
        perror("listen() failed.");
        return;
    }

    fprintf(stdout, "Server is waiting for client to connect...\n");

    int sock2 = accept(sock1, NULL, NULL);

    if (sock2 > 0)
    {
        fprintf(stdout, "Server has a client!\n");

        FILE* fp = fopen("/etc/hosts", "r");

        if (fp)
        {
            char buf[50];
            int  bytesRead = 0;
            int  error = 0;

            while (!error && (bytesRead = fread(buf, sizeof(char), sizeof(buf), fp)) > 0)
            {
                int bytesWritten = 0;

                while (bytesWritten != bytesRead)
                {
                    int ret = send(sock2, buf + bytesWritten, bytesRead - bytesWritten, 0);

                    if (ret > 0)
                    {
                        bytesWritten += ret;
                    }
                    else if (ret < 0)
                    {
                        if (errno != EAGAIN && errno != EINTR)
                        {
                            perror("Server has error writing.");
                            error = 1;
                            break;
                        }
                    }
                }
            }
            fclose(fp);

            fprintf(stdout, "Server is done sending file.\n");
        }
        else
        {
            perror("Server failed to open file.");
        }

        close(sock2);
    }
    else
    {
        perror("accept() failed.");
    }
}


void Socket_client()
{
    int sock = socket(AF_INET,SOCK_STREAM,0);

    struct timeval timeout = { 3, 0 };
    setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const void*) &timeout, sizeof(timeout));

    struct sockaddr_in serv;
    memset(&serv, 0, sizeof(serv));

    serv.sin_port        = htons(PORT);
    serv.sin_family      = AF_INET;
    serv.sin_addr.s_addr = htonl(INADDR_ANY);

    printf("Client attempting connection....\n");

    if (connect(sock, (struct sockaddr*) &serv, sizeof(serv)) == 0)
    {
        fprintf(stdout, "Client succesfully connected!\n");

        FILE* fp = fopen("client_new.txt", "w");

        if (fp)
        {
            int done = 0;

            while (!done)
            {
                char buf[50] = {0};

                int bytesRcvd = recv(sock, buf, sizeof(buf), 0);

                if (bytesRcvd > 0)
                {
                    fwrite(buf, sizeof(char), bytesRcvd, fp);
                }
                else if (bytesRcvd == 0)
                {
                    fprintf(stdout, "Client has not received data from server after some time.\n");
                    done = 1;
                }
                else if (bytesRcvd < 0)
                {
                    perror("Failed to get data from the server.");
                    done = 1;
                }
            }

            fclose(fp);
        }
        else
        {
            perror("Client failed to open file.");
        }

        close(sock);
    }
    else
    {
        perror("Client failed to connect to server.");
    }

    fprintf(stdout, "Client is done!\n");
}

P.S. What ever Socket Programming tutorial you are using is probably obsolete or poorly written. May I suggest that you consider using this one instead: http://beej.us/guide/bgnet/output/ht...age/bgnet.html

cliffordw 07-18-2012 09:29 AM

Hi again,

Just one more observation I forgot to mention erlier: in the original code you use fread() and write() to read & send fixed blocks of 50 bytes of data in the server. In the client you try and read() the same 50 bytes. All of this works on fixed blocks of raw data, not strings (no null termination). You then try and fprintf() it to the file on the client, though. This is bound to cause serious problems.

In addition to doing the much needed error checking, dwhitney67's example above uses fwrite() instead, and checks the number of bytes read/send/received/written, which solves this problem (and a few others).

dwhitney67 07-18-2012 09:58 AM

Quote:

Originally Posted by cliffordw (Post 4731702)
Hi again,

Just one more observation I forgot to mention erlier: in the original code you use fread() and write() to read & send fixed blocks of 50 bytes of data in the server. In the client you try and read() the same 50 bytes. All of this works on fixed blocks of raw data, not strings (no null termination). You then try and fprintf() it to the file on the client, though. This is bound to cause serious problems.

I agree. The other issue was the OP's issuance of the string "quit1234" to mark the end of the data. There is no guarantee that the client would receive this message as is; it could be included within a previous packet, or even arrive in multiple packets (ie the string would be split). Thus the usage of strcmp() in the client is likely not to return a value of 0 to mark the end of processing.

jack.sully 07-18-2012 11:38 AM

Thanks a lot.

It's working now

jack.sully 07-19-2012 07:22 AM

Just one query, you have not passed IP address in the code .Like we generally pass

serv.sin_addr.s_addr = inet_addr("127.0.0.1");

for tranferring file on local machine.

U have used

serv.sin_addr.s_addr = htonl(INADDR_ANY);

Can u please explain.

dwhitney67 07-19-2012 08:12 AM

Quote:

Originally Posted by jack.sully (Post 4732624)
Just one query, you have not passed IP address in the code .Like we generally pass

serv.sin_addr.s_addr = inet_addr("127.0.0.1");

for tranferring file on local machine.

U have used

serv.sin_addr.s_addr = htonl(INADDR_ANY);

Can u please explain.

If you are interested in binding or connecting only to the localhost, then your way is fine. However if you want to use all interfaces on a system (e.g. lo, eth0, etc), then INADDR_ANY is used.

Bear in mind, that per the man-page for inet_addr(), its use is not recommended. Use of either inet_aton(), inet_pton() or getaddrinfo() is preferred.


All times are GMT -5. The time now is 06:36 PM.