Skip to content

Instantly share code, notes, and snippets.

@thentenaar
Created January 26, 2015 20:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thentenaar/e2eecbb92a66509ec602 to your computer and use it in GitHub Desktop.
Save thentenaar/e2eecbb92a66509ec602 to your computer and use it in GitHub Desktop.
Simple echo server: Refactor #1: Move the socket setup code into its own function.
/**
* Simple echo server
*
* This program listens for connections on the
* loopback interface, on port 9999. Upon connecting,
* The first line we read, of up to BUF_LEN bytes, is
* then sent back to the sender, and the connection
* is closed.
*
* Refactor #1 - Move socket creation code into its own
* function.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define BUF_LEN 25
static char buf[BUF_LEN + 1];
/**
* Create a socket which will be listening for connections
* on localhost:9999.
*/
int setup_socket()
{
int fd, i=1;
struct sockaddr_in sa;
/* Open a TCP socket */
if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
perror("socket");
return -1;
}
/* Let's ensure we can reuse our address */
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(int));
/* This will bind to localhost:9999 */
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(9999);
sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
perror("bind");
close(fd);
return -1;
}
/* Listen for one connection at a time */
if (listen(fd, 1) < 0) {
perror("listen");
close(fd);
return -1;
}
return fd;
}
int main(int argc, char *argv[])
{
int fd, c_fd = 0, i;
unsigned int bytes_read = 0;
if ((fd = setup_socket()) < 0)
return EXIT_FAILURE;
while (1) {
/* Initialize our state variables and wait for connections */
c_fd = 0;
bytes_read = 0;
memset(buf, 0, BUF_LEN+1);
if ((c_fd = accept(fd, NULL, NULL)) < 0) {
perror("accept");
break;
}
/* We've got a live one. */
printf("Got connection\n");
/**
* Read data until the buffer is full, we get an EOF, or
* we've read a '\n'.
*/
while (bytes_read < BUF_LEN) {
i = recv(c_fd, buf + bytes_read, BUF_LEN - bytes_read, 0);
if (!i) break;
if (i < 0) {
if (errno == EINTR)
continue;
perror("recv");
close(c_fd);
break;
}
bytes_read += i;
if (strchr(buf, '\n')) break;
}
/* Echo data if we got it */
if (bytes_read) {
buf[bytes_read + 1] = 0;
printf("Read: %s\n", buf);
if (send(c_fd, buf, bytes_read, 0) < 0)
perror("send");
}
/* Kill this one, and wait for the next victim... */
close(c_fd);
}
if (c_fd) close(c_fd);
close(fd);
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment