86 lines
2.0 KiB
C
86 lines
2.0 KiB
C
#include <netinet/in.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
|
|
static void fmt_inaddr(char *buffer, const struct sockaddr_in *inaddr) {
|
|
uint8_t a = (uint8_t) inaddr->sin_addr.s_addr;
|
|
uint8_t b = (uint8_t) (inaddr->sin_addr.s_addr >> 8);
|
|
uint8_t c = (uint8_t) (inaddr->sin_addr.s_addr >> 16);
|
|
uint8_t d = (uint8_t) (inaddr->sin_addr.s_addr >> 24);
|
|
uint16_t port = ntohs(inaddr->sin_port);
|
|
sprintf(buffer, "%hhu.%hhu.%hhu.%hhu:%hu", a, b, c, d, port);
|
|
}
|
|
|
|
int main(int argc, const char **argv) {
|
|
int fd = socket(AF_INET, SOCK_STREAM, 0);
|
|
|
|
if (fd < 0) {
|
|
perror("socket()");
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
struct sockaddr_in sa;
|
|
socklen_t slen;
|
|
char buffer[256];
|
|
|
|
memset(&sa, 0, sizeof(sa));
|
|
sa.sin_family = AF_INET;
|
|
sa.sin_port = htons(4321);
|
|
sa.sin_addr.s_addr = INADDR_ANY;
|
|
|
|
if (bind(fd, (const struct sockaddr *) &sa, sizeof(sa)) != 0) {
|
|
perror("bind()");
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
if (listen(fd, 64) != 0) {
|
|
perror("listen()");
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
while (1) {
|
|
int rfd;
|
|
|
|
slen = sizeof(sa);
|
|
if ((rfd = accept(fd, (struct sockaddr *) &sa, &slen)) < 0) {
|
|
perror("accept()");
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
fmt_inaddr(buffer, &sa);
|
|
printf("Received connection from %s\n", buffer);
|
|
|
|
while (1) {
|
|
ssize_t len;
|
|
|
|
if ((len = recv(rfd, buffer, sizeof(buffer), 0)) < 0) {
|
|
perror("recv()");
|
|
break;
|
|
}
|
|
|
|
if (len == 0) {
|
|
break;
|
|
}
|
|
|
|
if (len >= 4 && !strncmp(buffer, "quit", 4)) {
|
|
break;
|
|
}
|
|
|
|
fwrite(buffer, 1, len, stdout);
|
|
|
|
if ((len = send(rfd, buffer, len, 0)) < 0) {
|
|
perror("send()");
|
|
break;
|
|
}
|
|
}
|
|
|
|
printf("Connection closed\n");
|
|
close(rfd);
|
|
}
|
|
|
|
return 0;
|
|
}
|