Thread: Basic C Socket Program Client/Server text file content transmission! DESPERATE HELP!!

  1. #1
    Registered User
    Join Date
    Oct 2009
    Posts
    20

    Basic C Socket Program Client/Server text file content transmission! DESPERATE HELP!!

    Hi everyone,

    This is my first post to these boards and I hate for it to be the way that it is but I'm pretty much desperate and I need urgent help. If I'm at all breaking the rules please let me know. I REALLY need help to get an assignment done, I don't want anyone to do it for me, I just need to get it done.

    I have about 40 hours to get this done and I don't plan on sleeping until it's done.

    The basic problem:

    I need to create a client/server program in C using sockets.

    I need the client to be prompted with a menu like "Enter a name".

    The client then enters a name eg "Billy Bob", this gets sent to the server.

    The server has a text file with a bunch of names listed like:

    Name Age Hair Color
    Billy Bob 18 Black
    James Lol 22 Brown
    Chris H 90 Red

    the server then receives the request sent from the server "Billy Bob" and looks in the test file and sends the client back "Billy Bob's is 18 years old, he has Black hair" or if the user requested a person not in the text file "sorry, that person does not exist".

    So basically I need a client to send a request, a server to act on that request and transmit the information back.

    I have searched for about 4 hours for a tutorial or something similar to this problem for about 4 hours now and the closest I have got is a tutorial on sending "Hello World" from the server to the client.

    That program is not very helpful, while I follow the tutorial it doesn't require the client to send anything to the server, and the server does not query, it just sends that no matter what.

    I am not asking for anyone to do this for me, I would just like some guidance on where to start, if anyone knows of any documents or anything that I can read which will assist me I will be very grateful.

    I'm generally not someone who leaves things to the last minute, and I really cannot afford to fail this assignment. If someone would be willing to help guide me through the assignment via an IM service I would happily give them some money, by no means do I want someone to do it for me, just some guidance and help to ensure I get it done.

    I'm a competent programmer in c++ but I'm fairly new to c, I've basically done 10 weeks of this subject, 4 weeks I was away overseas for family issues. I've learned most things up to creating basic threads.

    Please, I'm pretty desperate and if anyone can help me I'll be greatly appreciative.

    Thanks guys!

    P.S Am I screwed? Do you personally think this task will be out of my league in the time I have to complete it (I'm really dying from stress here as I really can't find anything to help me and I feel like I'm running out of time)

  2. #2
    Registered User
    Join Date
    Oct 2009
    Posts
    20
    The spacing where I described the text file didn't come out as expected, but hopefully you get the basic idea...

    It has information listed in an order NAME INFO INFO the information on each line is associated with the persons name.

    Client sends request of persons name, server sends back persons details after receiving query.

    Thanks again

  3. #3
    Registered User
    Join Date
    Oct 2009
    Posts
    20
    Oh and to be more clear on the program I have already gone through and understand (mostly understand).

    The output from the client that I compiled after running like ./client 127.0.0.1

    Received: Hello, world!

    The server simply gives:
    server starts listnening ...

    and then

    server: got connection from 127.0.0.1

    this is all the program does, I mean it's a start because I can at least connect, but it doesn't do any query/response type stuff that I need.

  4. #4
    Registered User
    Join Date
    Oct 2009
    Posts
    20
    Another note, I won't abandon this thread, and I haven't posted on any other forums.

    Just letting you know if you provide help, I will get it and respond as soon as possible!

    I see a lot of message boards where people ask for help, someone responds with a very lengthy reply and the OP never responds again. I'll definitely be waiting for a response and will acknowledge any responses. If this helps provide incentive to post

    thanks again!

  5. #5
    Registered User
    Join Date
    Oct 2009
    Posts
    20
    I'm running Ubuntu 9.04 - the Jaunty Jackalope and using gcc compiler.

  6. #6
    Registered User
    Join Date
    Oct 2009
    Posts
    20
    my msn address is [email protected] if anyone can add me there for assistance... thanks again

  7. #7
    Make Fortran great again
    Join Date
    Sep 2009
    Posts
    1,413
    Yeah, it doesn't look like anyone here is going to help you...shouldn't have procrastinated :<

  8. #8
    Registered User
    Join Date
    Oct 2009
    Posts
    20
    Quote Originally Posted by Epy View Post
    Yeah, it doesn't look like anyone here is going to help you...shouldn't have procrastinated :<


    It wasn't about procrastinating, it was more about being bailed on by group members for two other assignments also due this week.

    Is the task really that difficult? Already able to setup a basic socket connection between a client and server, is it not a simple step to modify so that I can make the server act on a clients request?

    I just need a place in my server code that I can receive a clients input and send something back to the client.

    Reading from a text file I won't have a problem with, the problem is knowing where and how to setup the connection that I can receive client input and act on it accordingly, then transmit back.

    I am having a lot of trouble with it and with little knowledge of sockets, I can't exactly make an accurate assumption on whether it's an easy task. However, having said that from the point of view I stand, the task seems doable, I just need some guidance.

    I am trying to work through it by myself, but knowing I have a bit of help somewhere would really comfort me.

    Thanks again

  9. #9
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Desperatenoob View Post
    Is the task really that difficult? Already able to setup a basic socket connection between a client and server, is it not a simple step to modify so that I can make the server act on a clients request?
    It shouldn't be that hard -- there are little pitfalls that may or may not happen, is all. Those can suck up time. You should post the code you have so far and indicate more clearly where your troubles lie. If the connection is good, all you have to do is use send() and recv() to transmit your message. Since it is a 1:1 client/server ratio (I think) you can use a blocking socket (the normative default). That means a recv() call at either end waits until a message arrives. So you always want to have some form of "exchange" to make sure everything keeps happening in the proper order. Make sense?
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  10. #10
    Registered User
    Join Date
    Oct 2009
    Posts
    20
    Quote Originally Posted by MK27 View Post
    Since it is a 1:1 client/server ratio (I think)
    Actually, it's not, we are meant to have up to 30 clients, does this add more complications? I've been reading up on it and I've found methods that use fork() to create a thread for each additional client.

    Quote Originally Posted by MK27 View Post
    That means a recv() call at either end waits until a message arrives. So you always want to have some form of "exchange" to make sure everything keeps happening in the proper order. Make sense?
    Yep, that makes perfect sense.

    I am currently going through a tutorial on the internet on Linux Howtos:

    Linux Howtos: C/C++ -> Sockets Tutorial

    I will post my code once I have gone through and understood everything that is happening and rewritten it in my own words as best I can. Of course I'll need to reference this site in my assignment, because I'm really not going to be changing much of the base code.

    Thanks a lot for your reply, MK.

    Do you think it's wise for me to start by making it for a 1:1 relationship, then if I have time modifying it for more users? Or would it be better to just jump into 30:1?

    Thanks again

  11. #11
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    A tip: it can be handy to make the first part of every message a number indicating the number of bytes in the transmission. So you grab that off, for example:
    Code:
    int length = *(int*)buffer;   /* buffer is the void* from receive */
    buffer += sizeof(int);  /* move the pointer forward past the number */
    That is the easiest way for the reciever, but it means you must send() an int first, not a number in a string. If you prefer to do that, then you read it off this way:
    Code:
    char length[8];
    scanf(buffer, "%7[0-9]:", length);   /* the colon is a definitive seperator */
    buffer += strlen(length+1);  /* move the pointer forward past the number, and the colon */
    int len = atoi(length);
    [...just saw your last message...hang on...]
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  12. #12
    Registered User
    Join Date
    Oct 2009
    Posts
    20
    Thanks MK

    I will come back to that after I finnish writing up this code. After I've typed it out I'll post it and explain where my complications lie.

    again thanks a lot.

  13. #13
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Desperatenoob View Post
    Do you think it's wise for me to start by making it for a 1:1 relationship, then if I have time modifying it for more users? Or would it be better to just jump into 30:1?
    Good thinking! I would definitely start with 1:1.

    Then: vis, forking for each client, that is one possibility if you want to make the connection persist. Every time you accept() a client, that client gets a new socket. However, you probably don't really need a persistant connection if the exchange is something like client logs on, client asks for file, server sends file, done. In that case, you can simply wait with accept() in a loop that answers and deals with every incoming call, and disconnects when the request is complete -- this is how an internet server works, more or less. Altho apache does fork, it does not fork for every request*, and it does not maintain open connections -- every request opens a new socket, then closes it when the request is complete. This method will work for an "unlimited" number of clients, but they get served one at a time. I do not know if a forking model -- where in theory, near simultaneous requests will be dealt with in parallel -- is faster than one which goes thru them one at a time. Either way, with <30 clients asking for (small) text files there unlikely to be any relevant delays at all by the server.

    If possible tho, check with your prof to make sure he is not expecting a forking model.

    *it does use a thread for each request, which is almost the same thing, but the premise is still that the threads do not persist. I do not think threading or forking is necessary at this scale. Of course, you may as well learn both methods. Which one you use now is up to you, I don't know the details of the requirements.
    Last edited by MK27; 10-21-2009 at 09:12 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  14. #14
    Registered User
    Join Date
    Oct 2009
    Posts
    20
    Code:
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    
    void errormsg(char *message) // Error message function
    {
      perror(message); // Show user error message
      exit(1);         // exit
    }
    
    int main (int argc, char *argv[])
    {
      int sockd;       // file descriptor for socket
      int newsockd;     // file descriptor for new socket
      int portnum;       // port number for transmissions
      int clientlength;  // length of client address
      int retval;        // return value
      
      char buffer[256];  
    
      struct sockaddr_in serv_addr, cli_addr;  // structure defined in netinet header file.
    
      if (argc < 2)     // Server must be initiated with a port.
        {
          fprintf(stderr,"Usage:./server Port \n");
          exit(1);
        }
    
      sockd = socket(AF_INET, SOCK_STREAM, 0); // AF_INET for internet domain, Stream Socket
      
      if (sockd == -1)
        error("ERROR: Opening socket failed");
    
      bzero((char *) &serv_addr, sizeof(serv_addr)); // Set all vals in serv_addr to zero
      
      portnum = atoi(argv[1]); // Gets user input and stores as port number
      serv_addr.sin_family = AF_INET; // Sets serv_addr in struct sock_addr_in
      serv_addr.sin_port = htons(portnum);  // change the port number from host to server format
      serv_addr.sin_addr.s_addr = INADDR_ANY;   // contains IP address of host
    
      // bind socket to address, cast serv_addr to type struct sockaddr
      if (bind(sockd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) 
        error("ERROR: Bind failed"); // present error if it returns -1 (fails)
    
      listen(sockd,5); // allow p to 5 connections that can wait while process handles an existing connection.
    
      clientlength = sizeof(cli_addr); // set clientlength variable to the length of client address
      // set reference to client address and length of client address
      newsockd = accept(sockd, (struct sockaddr *) &cli_addr, &clientlength);
      if (newsockd < 0)
        error("ERROR: couldn't establish connection with client");
    
      bzero(buffer,256);  // zero the buffer values
      retval = read(newsockd,buffer,255); // store the new socket file description into the buffer
      if (retval < 0)
        error("ERROR: could not read new socket file description");
      printf("Message received from client is: %s", buffer); // show users output
    
      // Receive user input here, go into text file and compare, grab a string
    
      retval = write(newsockd, "I got your message", 18);
      if (retval < 0)
        error("ERROR: could not write to socket");
      
      // Send string to user there ^
    
      return 0;
    }
    Ok, here is my code for the server at the moment. This was made from going through the tutorial step by step. I feel confident to this point.

    Now my strategy is going to be to deal with "buffer" as if I was in a seperate program, and simply trying to make a program that was given an array of characters and asked to find information in a text file. I'm going to get the information I need from the text file, and then return the result in another char[].

    Then the only thing left to do is send it to the user replacing "I got your message" with the new string I got above.

    Would this be correct?

    I'm going to start working on the C code to search a text file and also retrieve text from a text file.

    P.S I think I do need to do it using threads, but I'll come back to that after I get it working 1:1, as I think I will at least achieve a pass if I get it working 1:1.

    Thanks again MK, really appreciate your help.

    EDIT: My server DOES compile, and works with the client code from that website. (not surprisingly as I didn't change much, basically just went through and typed it up to understand it)

  15. #15
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    It is better to use send() and recv() than read() and write(). There's not much difference, just send() and recv() are intended for networking, are more portable, and have a bit more functionality.

    Hopefully you can see the value of transmitting the length. Then you can just use a (fairly small) fixed size buffer, which you recv upto that size. Once you have the length, you malloc another buffer for the data, copy the first bunch in, then keep looping length/bufsize times (plus the length%bufsize remainder!) and strcat into your malloc'd data pointer. You can put all that in a discrete function too, and just return the malloc'd pointer containing all the recieved data (so the function accepts a socket number as a param). A single send() can be processed by multiple recvs -- the socket waits.

    On thing I would do is separate the socket stuff out into it's own, reusable function like this:
    Code:
    int inet_sockto (char *addrstr, int port, int nblock) {
            struct sockaddr_in server;
            int sock = -1;
            if ((sock=socket(PF_INET, SOCK_STREAM, 0))<3) { perror("socket"); return sock; }
            server.sin_family=AF_INET;      
            server.sin_port=htons(port);
            inet_aton(addrstr,(struct in_addr*)&server.sin_addr.s_addr);
            memset(&(server.sin_zero), '\0', 8);
            if (nblock)  fcntl(sock,F_SETFL,O_NONBLOCK);
            if (connect(sock,(struct sockaddr*)&server,sizeof(struct sockaddr))!=0) {
                    perror("connect");
                    close(sock);
                    return -666;
            }
            return sock;
    }
    This works for a client; it accepts a string address (eg. "100.200.300.400"), a port number, and a flag. It returns the connected socket, which is all you actually need.

    A parallel to this in the server is accept() itself, which returns a socket connected to the client.
    Last edited by MK27; 10-21-2009 at 09:50 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 09-16-2009, 06:00 AM
  2. sequential file program
    By needhelpbad in forum C Programming
    Replies: 80
    Last Post: 06-08-2008, 01:04 PM
  3. Need a suggestion on a school project..
    By Screwz Luse in forum C Programming
    Replies: 5
    Last Post: 11-27-2001, 02:58 AM
  4. Problems displaying content of a text file
    By melissa in forum C++ Programming
    Replies: 5
    Last Post: 11-12-2001, 06:13 PM
  5. My program, anyhelp
    By @licomb in forum C Programming
    Replies: 14
    Last Post: 08-14-2001, 10:04 PM