Thread: Client/Server Switch using Buffer

  1. #1
    Registered User
    Join Date
    May 2008
    Posts
    19

    Client/Server Switch using Buffer

    Hello and Happy Thanksgiving. I am working on a simple TCP Client Server poker game, and have run into a little problem. I am not the best programmer. I am modifying a previously used TCP Echo program for this.

    I want the client to simply do display work, while the server handles everything else. In the client, I display a menu, and then read the input into buffer, and send to server. What I then want to do is take the input that is sent to server, and run it through a switch statement to send it to the play function, or the stats function, or quit. I am unsure of how to do a switch statement, or anything of the sort using the buffer however. I know how to use switch statements of course, just not with a buffer that is sent from another program. Any help is appreciated.

    Client:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h> 
    #include <string.h>
    
    void error(char *msg)
    {
        perror(msg);
        exit(0);
    }
    
    int main(int argc, char *argv[])
    {
        int sockfd, portno, n;
    	int choice;
        struct sockaddr_in serv_addr;
        struct hostent *server;
    
        char buffer[256];
        if (argc < 3) {
           fprintf(stderr,"usage %s hostname port\n", argv[0]);
           exit(0);
        }
        portno = atoi(argv[2]);
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd < 0) 
            error("ERROR opening socket");
        server = gethostbyname(argv[1]);
        if (server == NULL) {
            fprintf(stderr,"ERROR, no such host\n");
            exit(0);
        }
        bzero((char *) &serv_addr, sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
        bcopy((char *)server->h_addr, 
             (char *)&serv_addr.sin_addr.s_addr,
             server->h_length);
        serv_addr.sin_port = htons(portno);
        if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0) 
            error("ERROR connecting");
    		
    	printf(" \n");
    	printf("*****************************************\n");
    	printf("Welcome to the World Famous Davis' Poker!\n");
    	printf("*****************************************\n");
    	printf(" \n");
    		
    	while (buffer != NULL)
    	{
    	
    		printf("Please select an action:\n");
    		printf("1 - Play Poker\n");
    		printf("2 - View Statistics\n");
    		printf("3 - Quit\n");
    		printf("\n");
    		printf("Selection: ");
    		
        bzero(buffer,256);
        fgets(buffer,255,stdin);
        n = write(sockfd,buffer,strlen(buffer));
        if (n < 0) 
             error("ERROR writing to socket");
        bzero(buffer,256);
        n = read(sockfd,buffer,255);
        if (n < 0) 
             error("ERROR reading from socket");
        printf("%s\n",buffer);
    	}
        return 0;
    }
    Server:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h> 
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <string.h>
    
    void error(char *msg)
    {
        perror(msg);
        exit(1);
    }
    
    int main(int argc, char *argv[])
    {
         int sockfd, newsockfd, portno, clilen;
         char buffer[256];
    	 char c;
    	 int choice;
         struct sockaddr_in serv_addr, cli_addr;
         int n;
    	
         if (argc < 2) {
             fprintf(stderr,"ERROR, no port provided\n");
             exit(1);
         }
         sockfd = socket(AF_INET, SOCK_STREAM, 0);
         if (sockfd < 0) 
            error("ERROR opening socket");
         bzero((char *) &serv_addr, sizeof(serv_addr));
         portno = atoi(argv[1]);
         serv_addr.sin_family = AF_INET;
         serv_addr.sin_addr.s_addr = INADDR_ANY;
         serv_addr.sin_port = htons(portno);
         if (bind(sockfd, (struct sockaddr *) &serv_addr,
                  sizeof(serv_addr)) < 0) 
                  error("ERROR on binding");
         listen(sockfd,5);
         clilen = sizeof(cli_addr);
         newsockfd = accept(sockfd, 
                     (struct sockaddr *) &cli_addr, 
                     &clilen);
         if (newsockfd < 0) 
              error("ERROR on accept");
    		  
    	while (buffer != NULL) {
         bzero(buffer,256);
         n = read(newsockfd,buffer,255);
         if (n < 0) error("ERROR reading from socket");
    	
         printf("Here is the message: %s\n",buffer);
         n = write(newsockfd,"I got your message",18);
         if (n < 0) error("ERROR writing to socket");
    	 }
         return 0; 
    }

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Happy Thanksgiving! Unfortunately, I don't think there's any way for you to do this unless there is a single byte in the buffer that will tell you what function to pass it to. As far as I know, switch statements only work on basic types like char, int, float, double, etc. (no arrays or structs), and your case statements can only be constant values. If you have the desired action stored in a single byte, you can do it like this:
    Code:
    switch (buf[ACTION_INDEX]) {
        case ACTION_PLAY:
            play_function(buf);
            break;
        ...
        default:
            // unknown action
            break;
    }
    Otherwise, your best alternative is to use a series of if-else if statements with strcmp or memcmp, like so:
    Code:
    #define ACTION_PLAY    "play"
    #define ACTION_STATS   "stat"
    ...
    if (!memcmp(buf+ACTION_INDEX, ACTION_PLAY, ACTION_LEN)) {
        play_function(buf);
    }
    else if (!memcmp(buf+ACTION_INDEX, ACTION_STATS, ACTION_LEN)) {
    }
    ...
    else {
        // unknown action
    }
    Where ACTION_INDEX is the byte offset (from 0) of the field in your buffer containing the action to perform, and ACTION_LEN is the number of bytes for the action field in your buffer.
    Last edited by anduril462; 11-25-2010 at 03:58 PM. Reason: added default case

  3. #3
    Registered User hellork's Avatar
    Join Date
    Nov 2010
    Posts
    39
    You could also use an enum.
    Code:
    #include <stdio.h>
    
    enum {play=1,stats,quit};
    int main (void){
        int input;
        scanf (" %d",&input);
        switch (input){
            case play:
            printf ("Play!\n");
            break;
            case stats:
            printf ("Stats!\n");
            break;
            default:
            printf ("Quitting...%i\n", input);
        } return 0;
    }
    generated with Anchor | freshmeat.net

  4. #4
    Registered User
    Join Date
    May 2008
    Posts
    19
    Since I am only inputting an integer anyway, be it '1' for play poker, '2' for view stats, etc, would there be an easier way to do this? Instead of reading in to a buffer, could I just scanf into a variable, say 'choice' and then send that variable, 'choice' in the
    Code:
    n = write(sockfd,buffer,strlen(buffer));
    call in place of buffer?

    Whatever I do, I just have to be able to send the input through write to the client, and do the switch and function calls there.

  5. #5
    Registered User
    Join Date
    Nov 2010
    Location
    xian china
    Posts
    31
    the second arg of the write functin is "const void *", you can read the num into an integer and pass the address of the integer to the second arg:
    Code:
    scanf("%d",&num);
    switch(num)
    {
       case 1:
        printf ("Play!\n");
          break;
    }
    write(sockfd,&num,1);
    try it ..

  6. #6
    Registered User
    Join Date
    May 2008
    Posts
    19
    Thank you.
    And then in the server, you could use what?
    Code:
    n = read(newsockfd, &choice, 1);
    Edit: I figured it out. Amazing what you can do with a little playing around haha. Thanks for the help. I'll update if I run into any more problems.
    Last edited by anndruu12; 12-01-2010 at 12:51 AM. Reason: Solved.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Lost with wrong output
    By erasm in forum C Programming
    Replies: 8
    Last Post: 10-06-2009, 06:44 AM
  2. Function call from another .c module
    By Ali.B in forum C Programming
    Replies: 14
    Last Post: 08-03-2009, 11:45 AM
  3. Multithreading (flag stopping a thread, ring buffer) volatile
    By ShwangShwing in forum C Programming
    Replies: 3
    Last Post: 05-19-2009, 07:27 AM
  4. Print out a buffer
    By SwarfEye in forum C Programming
    Replies: 4
    Last Post: 09-08-2006, 09:32 AM
  5. buffer contents swapping
    By daluu in forum C++ Programming
    Replies: 7
    Last Post: 10-14-2004, 02:34 PM