Home > Back-end >  what happen when you run client without server running?
what happen when you run client without server running?

Time:08-07

I got an interview question in sockets in c programming I got two files server.c and client.c

I was asked what will happen if you run a client when the server is not running : more specifically

run ./client localhost without running ./server in a different terminal

and I didn't know the answer (obviously it won't connect but what will happen I don't know) they wanted an answer that was related to the sockets

when I checked in Wireshark to see if I can get some information I saw this: the focus on the red record of the TCP sockets

the focus on the red record of the TCP sockets and the one record above it.

9999 is the port of the server what is the meaning of every parameter here?

56020 ->9999 [SYN] Seq=0 Win=65495 Len=0 MSS=65495 SACK_PERM=1 TSval=736093598 TSecr=0 WS=128

and also what is the meaning of

9999 -> 56020 [RST, ACK] Seq=1 Ack=1 Win=0 Len=0

I tried to look for the meaning in google but didn't find results that related to sockets. thank you very much in advanced!

code for the client.c

// to run in the terminal compile with 
// gcc -o client client.c -Wall  
// then run the following command:
// ./client localhost

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>

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

#define SIM_LENGTH 10
// #define IP_ADDRESS "127.0.0.1" // from the last part we put this in comment and resolve it with gethostbyname
#define PORT 9999

int main(int argc, char *argv[])
{
  int sock;
  struct sockaddr_in cli_name;
  int count;
  int value;
  char *hostname;
  char *hostaddr;
  struct addrinfo *res;
  struct sockaddr_in *saddr;
  printf("Client is alive and establishing socket connection.\n");
  printf("%d  %s\n", argc, argv[1]);
  if (argc != 2)
  {
    perror("Usage: hostnamelookup <hostname> error \n");
    exit(1);
  }

  hostname = argv[1]; // hostname is the first argument
  printf("Hostname is %s\n", hostname);

  if (0 != getaddrinfo(hostname, NULL, NULL, &res)) // getaddrinfo is a function that returns a struct addrinfo* that
  // contains a linked list of struct addrinfo (from nslookup.c)
  {
    fprintf(stderr, "Error in resolving hostname %s\n", hostname);
    exit(1);
  }

  sock = socket(AF_INET, SOCK_STREAM, 0);
  if (sock < 0)
  {
    perror("Error opening channel");
    close(sock);
    exit(1);
  }

  saddr = (struct sockaddr_in *)res->ai_addr; // get the address of the server socket address structure (from nslookup.c)
  hostaddr = inet_ntoa(saddr->sin_addr);      // get the IP address of the server (from nslookup.c)

  bzero(&cli_name, sizeof(cli_name));
  cli_name.sin_family = AF_INET;
  cli_name.sin_addr.s_addr = inet_addr(hostaddr); // set the IP address of the client (from nslookup.c)
  cli_name.sin_port = htons(PORT);

  if (connect(sock, (struct sockaddr *)&cli_name, sizeof(cli_name)) < 0)
  {
    perror("Error establishing communications");
    close(sock);
    exit(1);
  }

  for (count = 1; count <= SIM_LENGTH; count  )
  {
    read(sock, &value, 4);
    printf("Client has received %d from socket.\n", value);
  }

  printf("Exiting now.\n");

  close(sock);
  exit(0);
}

server.c

// to run in the terminal compile with 
// gcc -o server server.c -Wall  
// then run the following command:
// ./server 
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define SIM_LENGTH 10
#define PORT 9999

int main(void)
{
  int sock;                     // socket descriptor
  int connect_sock;             // socket descriptor for the connection
  struct sockaddr_in serv_name; // server socket address structure
  socklen_t len;                // length of the socket address structure
  int count;                    // number of bytes received

  sock = socket(AF_INET, SOCK_STREAM, 0); // create a socket
                                          // check if the socket is valid
  if (sock < 0)
  {
    perror("Error opening channel");
    exit(1);
  }
  // initialize the server socket address structure
  bzero(&serv_name, sizeof(serv_name)); // clear the structure
  serv_name.sin_family = AF_INET;       // set the family to Internet
  serv_name.sin_port = htons(PORT);     // set the port number

  // check if the bind is successful
  if (bind(sock, (struct sockaddr *)&serv_name, sizeof(serv_name)) < 0) // bind the socket to the server address
  {
    perror("Error on binding");
    exit(1);
  }

  // listen for connections
  if (listen(sock, 1) < 0) // listen for connections on the socket
  {
    perror("Error on listening");
    exit(1);
  }

  len = sizeof(serv_name); // get the length of the socket address structure

  connect_sock = accept(sock, (struct sockaddr *)&serv_name, &len); // accept a connection on the socket
                                                                    // check if the connection is valid
  if (connect_sock < 0)
  {
    perror("Error on accepting");
    exit(1);
  }
  for (count = 1; count <= SIM_LENGTH; count  ) // loop to send the data
  {
    write(connect_sock, &count, 4);                      // send the data
    printf("Server has written %d to socket.\n", count); // print the data
  }

  close(connect_sock); // close the connection
  close(sock);         // close the socket
}

CodePudding user response:

If the host on that IP is completely down and unreachable (or the destination port is effectively firewalled), then the client will retry initiating the three way handshake a few times before timing out and bubbling up an error to the socket application calling connect.

If the host is up, but not listening on the expected port, it will send back an RST in response to receiving SYN from the client. That will effectively tell the client to "go away, I'm not listening". And the TCP stack will again bubble up an error to the socket application to trigger its connect call to return an error.

  • Related