Skip to content

Instantly share code, notes, and snippets.

@rosalogia
Last active November 28, 2022 19:44
Show Gist options
  • Save rosalogia/d38104430b3fa50297d73a1819474d8c to your computer and use it in GitHub Desktop.
Save rosalogia/d38104430b3fa50297d73a1819474d8c to your computer and use it in GitHub Desktop.
Simple echo server impl. in C
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
int main() {
// First declare some basic known information about our socket
// in an addrinfo struct named hints, then use that struct to
// infer the remaining addrinfo fields needed to create and bind
// our socket
struct addrinfo hints, *res;
// Clearing the hints struct; this is important!
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET; // Use ipv4 addresses
hints.ai_socktype = SOCK_STREAM; // Use TCP rather than UDP
// Fill *res with a more complete addrinfo based on the hints we provided
getaddrinfo("127.0.0.1", "5000", &hints, &res);
// Initialize and bind our socket file descriptor using information from our
// newly-filled result addrinfo
int socket_fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (socket_fd == -1) {
perror("Error while creating socket");
return -1;
}
if (bind(socket_fd, res->ai_addr, res->ai_addrlen) == -1) {
perror("Error occurred while binding socket");
return -1;
}
if (listen(socket_fd, 20) == -1) {
perror("Error occurred while listening on socket");
return -1;
}
// Declare:
// - A sockaddr_storage for storing the address info of the client
// - A file descriptor for the client socket
// - An integer for storing the number of bytes read from the client
// - A socklen_t for storing the size of the client's address
// - A char buffer for storing the incoming message
struct sockaddr_storage incoming_addr;
int incoming_socket, read;
socklen_t addr_size = sizeof(incoming_addr);
char buff[1024];
// Accept loop
while (1) {
incoming_socket = accept(socket_fd, (struct sockaddr*) &incoming_addr, &addr_size);
if (incoming_socket == -1) {
perror("Error occurred while accepting on socket");
continue;
}
// Let's handle reading/writing in a child process so we
// can continue to accept new connections in the parent process
if (!fork()) {
// We don't need the server's socket fd in this child process
close(socket_fd);
while (1) {
// Read at most 1024 bytes from the client's socket into buff,
// with no added flags
read = recv(incoming_socket, buff, 1024, 0);
if (read < 0) {
perror("Error occurred while reading from client");
return -1;
}
// Reading in 0 bytes means the client has closed the connection
if (read == 0) {
printf("Client closed the connection\n");
return -1;
}
if (send(incoming_socket, buff, read, 0) < 0) {
perror("Error occurred while writing to client");
return -1;
}
}
close(incoming_socket);
}
close(incoming_socket);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment