LinuxQuestions.org
Review your favorite Linux distribution.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 07-17-2012, 09:06 PM   #1
jack.sully
Member
 
Registered: Jul 2012
Posts: 38

Rep: Reputation: Disabled
"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.
 
Old 07-18-2012, 12:45 AM   #2
cliffordw
Member
 
Registered: Jan 2012
Location: South Africa
Posts: 509

Rep: Reputation: 203Reputation: 203Reputation: 203
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!
 
Old 07-18-2012, 06:43 AM   #3
jack.sully
Member
 
Registered: Jul 2012
Posts: 38

Original Poster
Rep: Reputation: Disabled
"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
 
Old 07-18-2012, 06:55 AM   #4
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by jack.sully View Post
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;
}

Last edited by dwhitney67; 07-18-2012 at 06:57 AM.
 
Old 07-18-2012, 07:06 AM   #5
piyush.sharma
Member
 
Registered: Jul 2012
Location: Delhi, India
Distribution: CentOS
Posts: 82

Rep: Reputation: Disabled
just try to print the return value of read() & write() functions, it will help to check whether some text has been processed or not.
 
Old 07-18-2012, 07:09 AM   #6
jack.sully
Member
 
Registered: Jul 2012
Posts: 38

Original Poster
Rep: Reputation: Disabled
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
 
Old 07-18-2012, 08:20 AM   #7
piyush.sharma
Member
 
Registered: Jul 2012
Location: Delhi, India
Distribution: CentOS
Posts: 82

Rep: Reputation: Disabled
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.
 
Old 07-18-2012, 08:21 AM   #8
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by jack.sully View Post
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
 
1 members found this post helpful.
Old 07-18-2012, 09:29 AM   #9
cliffordw
Member
 
Registered: Jan 2012
Location: South Africa
Posts: 509

Rep: Reputation: 203Reputation: 203Reputation: 203
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).
 
Old 07-18-2012, 09:58 AM   #10
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by cliffordw View Post
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.
 
Old 07-18-2012, 11:38 AM   #11
jack.sully
Member
 
Registered: Jul 2012
Posts: 38

Original Poster
Rep: Reputation: Disabled
Thanks a lot.

It's working now
 
Old 07-19-2012, 07:22 AM   #12
jack.sully
Member
 
Registered: Jul 2012
Posts: 38

Original Poster
Rep: Reputation: Disabled
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.
 
Old 07-19-2012, 08:12 AM   #13
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by jack.sully View Post
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.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
unpredictable "delete" "move to trash" or "cut" file menu option dorianrenato Linux - General 3 11-28-2011 06:41 PM
Socket Programming making use of "select()" and "writefds" johncsl82 Programming 10 11-13-2011 12:27 PM
Socket "File Descriptor", Where is it? FatalKeystroke Programming 5 11-12-2010 10:10 PM
Reuse socket fails "Address already in use" or "Connection refused" dec10 Programming 3 05-15-2010 12:14 PM
DVD automount fails with "CDROM not ready yet" and "unaligned transfer" erica Linux - Hardware 1 12-14-2009 07:59 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

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

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration