Thread: C - Server/Client Example

  1. #1
    Registered User
    Join Date
    Nov 2017
    Posts
    18

    C - TCP Server/Client Example

    So I can run the server code with:
    ./server

    But how can I run the client code?
    I tried with:
    ./client name file.txt
    "42416 segmentation fault (core dumped)"


    Where “name” is the hostname given by “gethostbyname” as seen in this example:
    C Program to display hostname and IP address - GeeksforGeeks
    and “file.txt” is a file in the same folder.

    Here's a description of the client code:
    "Now let us look at the client code. To understand how it works, it is necessary to understand how it is invoked. Assuming it is called client, a typical call is:
    client flits.cs.vu.nl usr/tom/filename >f
    This call only works if the server is already running on flits.cs.vu.nl and the file usr/tom/filename exists and the server has read access to it.

    The client code starts with some includes and declarations. Execution begins by checking to see if it has been called with the right number of arguments(argc = 3 means the program plus two arguments) Note that argv[1] contains the server’s name (e.g, flits.cs.vu.nl) and is converted to an IP adress by gethostbyname. "

    client.c
    Code:
    /* This page contains the client program. The following one contains the
     * server program. Once the server has been compiled and started, clients
     * anywhere on the Internet can send commands (file names) to the server.
     * The server responds by opening and returning the entire file requested.
     */
    
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>
     #include <stdio.h>
    
    #define SERVER_PORT 12345   /* arbitrary, but client and server must agree */
    #define BUF_SIZE 4096     /* block transfer size */
    
    int main(int argc, char **argv)
    {
      int c, s, bytes;
      char buf[BUF_SIZE];     /* buffer for incoming file */
      char obuf[BUF_SIZE];    /* buffer for outgoing file */
      struct hostent *h;      /* info about server */
      struct sockaddr_in channel;   /* holds IP address */
    
      if (argc != 3) fatal("Usage: client server-name file-name");
      h = gethostbyname(argv[1]);   /* look up host's IP address */
      if (!h) fatal("gethostbyname failed");
    
      s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
      if (s < 0) fatal("socket");
      memset(&channel, 0, sizeof(channel));
      channel.sin_family= AF_INET;
      memcpy(&channel.sin_addr.s_addr, h->h_addr, h->h_length);
      channel.sin_port= htons(SERVER_PORT);
      c = connect(s, (struct sockaddr *) &channel, sizeof(channel));
      if (c < 0) fatal("connect failed");
    
      /* Connection is now established. Send file name including 0 byte at end. */
      write(s, argv[2], strlen(argv[2])+1);
    
      /* Go get the file and write it to a local file 
         (new or existing, overwritten) of the same name. */
      FILE *dst;
    
      sprintf(obuf, "out/%s", argv[2]);
    
      dst = fopen(obuf, "w+");
      while (1) {
            bytes = read(s, buf, BUF_SIZE); /* read from socket */
            if (bytes <= 0) exit(0);  /* check for end of file */
            fwrite(buf, sizeof(char), bytes, dst);
            // write(1, buf, bytes);    /* write to standard output */
      }
      fclose(dst);
    }
    
    fatal(char *string)
    {
      printf("%s\n", string);
      exit(1);
    }
    server.c
    ast_networks_5e_tcp_client.c * GitHub


    Last edited by Heisenberg800; 04-18-2021 at 04:39 PM.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    So run the code in the debugger and find out more information.

    1. Compile with debug information
    gcc -g -o client client.c

    2. Load into the debugger
    gdb ./client

    3. At the next prompt type
    run name file.txt

    4. When it crashes, use the following commands
    bt - print the current stack trace, which is the path the code took to crash.
    frame 1 - each function in the bt trace has a number. Use the frame command to jump to that function.
    print dst - print allows you to print variables in their current state, for example your file handle if you'd chosen the main functions frame.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Sep 2020
    Posts
    424
    Even just enabling warnings on your compiler will help...

    Code:
    gcc -o main main.c -Wall -pedantic -O4
    main.c: In function ‘main’:
    main.c:24:18: warning: implicit declaration of function ‘fatal’ [-Wimplicit-function-declaration]
       24 |   if (argc != 3) fatal("Usage: client server-name file-name");
          |                  ^~~~~
    main.c:30:3: warning: implicit declaration of function ‘memset’ [-Wimplicit-function-declaration]
       30 |   memset(&channel, 0, sizeof(channel));
          |   ^~~~~~
    main.c:30:3: warning: incompatible implicit declaration of built-in function ‘memset’
    main.c:12:1: note: include ‘<string.h>’ or provide a declaration of ‘memset’
       11 | #include <stdio.h>
      +++ |+#include <string.h>
       12 |
    main.c:32:3: warning: implicit declaration of function ‘memcpy’ [-Wimplicit-function-declaration]
       32 |   memcpy(&channel.sin_addr.s_addr, h->h_addr, h->h_length);
          |   ^~~~~~
    main.c:32:3: warning: incompatible implicit declaration of built-in function ‘memcpy’
    main.c:32:3: note: include ‘<string.h>’ or provide a declaration of ‘memcpy’
    main.c:38:3: warning: implicit declaration of function ‘write’; did you mean ‘fwrite’? [-Wimplicit-function-declaration]
       38 |   write(s, argv[2], strlen(argv[2])+1);
          |   ^~~~~
          |   fwrite
    main.c:38:21: warning: implicit declaration of function ‘strlen’ [-Wimplicit-function-declaration]
       38 |   write(s, argv[2], strlen(argv[2])+1);
          |                     ^~~~~~
    main.c:38:21: warning: incompatible implicit declaration of built-in function ‘strlen’
    main.c:38:21: note: include ‘<string.h>’ or provide a declaration of ‘strlen’
    main.c:48:17: warning: implicit declaration of function ‘read’; did you mean ‘fread’? [-Wimplicit-function-declaration]
       48 |         bytes = read(s, buf, BUF_SIZE); /* read from socket */
          |                 ^~~~
          |                 fread
    main.c:49:25: warning: implicit declaration of function ‘exit’ [-Wimplicit-function-declaration]
       49 |         if (bytes <= 0) exit(0);  /* check for end of file */
          |                         ^~~~
    main.c:49:25: warning: incompatible implicit declaration of built-in function ‘exit’
    main.c:12:1: note: include ‘<stdlib.h>’ or provide a declaration of ‘exit’
       11 | #include <stdio.h>
      +++ |+#include <stdlib.h>
       12 |
    main.c: At top level:
    main.c:56:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
       56 | fatal(char *string)
          | ^~~~~
    main.c: In function ‘fatal’:
    main.c:59:3: warning: incompatible implicit declaration of built-in function ‘exit’
       59 |   exit(1);
          |   ^~~~
    main.c:59:3: note: include ‘<stdlib.h>’ or provide a declaration of ‘exit’

  4. #4
    Registered User
    Join Date
    Sep 2020
    Posts
    424
    It looks like you are not checking that you are correctly opening the output file

    Code:
      dst = fopen(obuf, "w+");
    You should check to see if dst is not NULL.

  5. #5
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    And:

    1- gethostbyname() is an old and obsolete function. Use getaddrinfo();
    2- sockaddr_in.sin_addr.s_addr is a simple 'unsigned int'. Don't need 'memcpy()' to write on it;
    3- Don't use write()/read() functions with sockets. Prefer sent()/recv().

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. UDP Client/Server in C
    By daniel212 in forum C Programming
    Replies: 1
    Last Post: 04-28-2019, 03:21 AM
  2. Replies: 4
    Last Post: 11-16-2018, 08:30 AM
  3. Client/server problem; server either stops receiving data or client stops sending
    By robot-ic in forum Networking/Device Communication
    Replies: 10
    Last Post: 02-16-2009, 11:45 AM
  4. Client/Server
    By zonf in forum Networking/Device Communication
    Replies: 13
    Last Post: 12-18-2005, 11:12 AM
  5. client - server
    By Micko in forum Networking/Device Communication
    Replies: 3
    Last Post: 07-12-2004, 02:49 AM

Tags for this Thread