Skip to content

Instantly share code, notes, and snippets.

@thentenaar
Created January 27, 2015 00:49
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/c638dacf9eea043d9148 to your computer and use it in GitHub Desktop.
Save thentenaar/c638dacf9eea043d9148 to your computer and use it in GitHub Desktop.
Simple echo server: Refactor #5: Reduce the depth of nesting in main().
/**
* 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.
*/
#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];
int main(int argc, char *argv[])
{
int fd, c_fd = 0, i = 1;
unsigned int bytes_read = 0;
struct sockaddr_in sa;
/* Open a TCP socket */
if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
perror("socket");
goto done;
}
/* 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");
goto done;
}
/* Listen for one connection at a time */
if (listen(fd, 1) < 0) {
perror("listen");
goto done;
}
loop:
/* Initialize our state variables and wait for connections */
bytes_read = 0;
memset(buf, 0, BUF_LEN+1);
if ((c_fd = accept(fd, NULL, NULL)) < 0) {
perror("accept");
goto loop;
}
/* 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'.
*/
readit:
if ((i = recv(c_fd, buf + bytes_read, BUF_LEN - bytes_read, 0)) > 0) {
bytes_read += i;
if (bytes_read < BUF_LEN && !strchr(buf, '\n'))
goto readit;
}
if (i < 0) {
if (errno == EINTR)
goto readit;
perror("recv");
goto next;
}
/* 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... */
next:
close(c_fd);
goto loop;
done:
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