-1

I am learning to work with C sockets, and have created very basic client and server programs for the same

Client Program

#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>          // contains the type definitions related to sockets
#include <sys/socket.h>         // contains the socket API

#include <netinet/in.h>         // used to store the address information

int main() {
    int network_socket;         // the socket is represented by an integer value, which can be used later to access the socket
    network_socket = socket(AF_INET, SOCK_STREAM, 0);           // opening a socket, defining the domain of the socket, type of socket, and protocol used

    struct sockaddr_in server_address;          // creating an address structure for the server
    server_address.sin_family = AF_INET;        // specifying the type of socket as internet
    server_address.sin_port = htons(9002);      // specifying the port number
    server_address.sin_addr.s_addr = INADDR_ANY; // specifying the address 

    int connection_status = connect(network_socket, (struct sockaddr*) &server_address, sizeof(server_address));        // The function to establish a connection
    if(connection_status == -1) {
        printf("Connetion Failed");
    }

    char server_response[256];
    recv(network_socket, &server_response, sizeof(server_response), 0);

    printf("The server sent the data: %s", server_response);

    return 0;
}

Server Program

#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/socket.h>

#include <netinet/in.h>

int main() {
    char server_message[256] = "You have reached the server\n";

    int server_socket;
    server_socket = socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in server_address;
    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(9002);
    server_address.sin_addr.s_addr = INADDR_ANY;

    bind(server_socket, (struct sockaddr*) &server_address, sizeof(server_address));
    listen(server_socket, 5);       // 5 indicates the backlog, i.e. how many sockets can be waiting for this connection at a given point of time

    int client_socket;
    client_socket = accept(server_socket, NULL, NULL);

    send(client_socket, server_message, sizeof(server_message), 0);

    return 0;
}

The given programs work well for the first time that I compile and run both of them, and I get the desired response upon running the client program

The server sent the data: You have reached the server

But when I try running the client program once again, I get the following message

Connection FailedThe server sent the data:

Even when I terminate the running server program, re-compile it and run it again, the same thing happens

8
  • 3
    Your server needs to accept connections in a loop. Right now, it accepts a connection, sends a message, and then exits. Commented Sep 25, 2023 at 7:41
  • 1
    Also please note that &server_response is a pointer to the array itself, and will have the type char (*)[256]. Usually you pass a pointer to the first element of the array, which is plain server_response. Commented Sep 25, 2023 at 7:42
  • 1
    You also need to add more error checking. And if there's an error, you should not continue the program as if nothing happened. Also note that TCP is a streaming protocol, with no packets or data boundaries, it's all a stream of bytes. As such, the data in a single send call might need multiple recv calls to be able to receive all the data. Commented Sep 25, 2023 at 7:44
  • 1
    The problem is the lack of error checking. If you add error checking you will likely see errors from the server. This is because you need to learn more about TCP, especially its states. After the server program exits, the socket is closed and will end up in the TIME_WAIT state. That will last for a couple of minutes. During that time you can't create a socket bound to the same interface and port again. Commented Sep 25, 2023 at 9:06
  • 1
    @Someprogrammerdude you are likely correct, however the server will enter TIME_WAIT only if the server closes its end of the connection first. As neither party is explicitly closing their sockets, whether the server enters TIME_WAIT is a timing issue dependent on which process actually terminates first. Commented Sep 25, 2023 at 23:45

1 Answer 1

0

I modified your server to support multiple clients sequentially using a loop.For supporting multiple concurrent clients, you have to use threads or NIO (e.g., epoll() or select()).

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <error.h>
#include <errno.h>

#define ERROR  -1
#define BACKLOG 5
#define NOEXIT  0
#define EXIT    1

const char *server_message = "You have reached the server\n";

int open_server_socket(int port) {
    int server_socket = socket(AF_INET, SOCK_STREAM, 0);  
    if (server_socket==ERROR) error(EXIT,errno, "socket");
    
    struct sockaddr_in server_address;
    server_address.sin_family = AF_INET;
    server_address.sin_port = port;
    server_address.sin_addr.s_addr = INADDR_ANY;
      
    if (bind(server_socket, (struct sockaddr*) &server_address,
             sizeof(server_address)) ==ERROR) error(EXIT, errno, "bind");

    if (listen(server_socket, BACKLOG) ==  ERROR) error(EXIT, errno, "listen");
    
    return server_socket;
}

void handle_client(int server_socket) {
  int client_socket = accept(server_socket, NULL, NULL);
  if (client_socket == ERROR) goto END;
  
  if (write(client_socket, server_message, sizeof(server_message) == ERROR))
    goto END;
  
  close(client_socket); 
  
 END:
  if(errno) error(NOEXIT, errno, "client");
}

int main() {
  int server_socket = open_server_socket(9005); 
  while(true) handle_client(server_socket);
}

In addition, I have mildly addressed the lack of error handling issue that was pointed out by Some programmer dude.

1
  • Lack of error handling is still a major problem. And will lead to the same problem that the OP have when closing down and restarting the server too close to each other. Commented Sep 25, 2023 at 12:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.