124 lines
3.0 KiB
C
124 lines
3.0 KiB
C
|
// https://systemprogrammingatntu.github.io/mp2/unix_socket.html
|
||
|
|
||
|
#define SOCKET_NAME "/tmp/resol.sock"
|
||
|
#define BUFFER_SIZE 12
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <sys/socket.h>
|
||
|
#include <sys/un.h>
|
||
|
#include <unistd.h>
|
||
|
|
||
|
int main(int argc, char *argv[]) {
|
||
|
struct sockaddr_un addr;
|
||
|
int down_flag = 0;
|
||
|
int ret;
|
||
|
int listen_socket;
|
||
|
int data_socket;
|
||
|
int result;
|
||
|
char buffer[BUFFER_SIZE];
|
||
|
|
||
|
/*
|
||
|
* In case the program exited inadvertently on the last run,
|
||
|
* remove the socket.
|
||
|
*/
|
||
|
unlink(SOCKET_NAME);
|
||
|
|
||
|
/* Create local socket. */
|
||
|
listen_socket = socket(AF_UNIX, SOCK_STREAM, 0);
|
||
|
if (listen_socket == -1) {
|
||
|
perror("socket");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* For portability clear the whole structure, since some
|
||
|
* implementations have additional (nonstandard) fields in
|
||
|
* the structure.
|
||
|
*/
|
||
|
memset(&addr, 0, sizeof(struct sockaddr_un));
|
||
|
|
||
|
/* Bind socket to socket name. */
|
||
|
addr.sun_family = AF_UNIX;
|
||
|
strncpy(addr.sun_path, SOCKET_NAME, sizeof(addr.sun_path) - 1);
|
||
|
|
||
|
ret = bind(listen_socket, (const struct sockaddr *) &addr,
|
||
|
sizeof(struct sockaddr_un));
|
||
|
if (ret == -1) {
|
||
|
perror("bind");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Prepare for accepting connections. The backlog size is set
|
||
|
* to 20. So while one request is being processed other requests
|
||
|
* can be waiting.
|
||
|
*/
|
||
|
ret = listen(listen_socket, 20);
|
||
|
if (ret == -1) {
|
||
|
perror("listen");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
/* This is the main loop for handling connections. */
|
||
|
for (;;) {
|
||
|
/* Wait for incoming connection. */
|
||
|
data_socket = accept(listen_socket, NULL, NULL);
|
||
|
if (data_socket == -1) {
|
||
|
perror("accept");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
result = 0;
|
||
|
for(;;) {
|
||
|
/* Wait for next data packet. */
|
||
|
ret = read(data_socket, buffer, BUFFER_SIZE);
|
||
|
if (ret == -1) {
|
||
|
perror("read");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
/* Ensure buffer is 0-terminated. */
|
||
|
buffer[BUFFER_SIZE - 1] = 0;
|
||
|
|
||
|
/* Handle commands. */
|
||
|
if (!strncmp(buffer, "DOWN", BUFFER_SIZE)) {
|
||
|
down_flag = 1;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (!strncmp(buffer, "END", BUFFER_SIZE)) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/* Add received summand. */
|
||
|
result += atoi(buffer);
|
||
|
}
|
||
|
|
||
|
/* Send result. */
|
||
|
sprintf(buffer, "%d", result);
|
||
|
ret = write(data_socket, buffer, BUFFER_SIZE);
|
||
|
|
||
|
if (ret == -1) {
|
||
|
perror("write");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
/* Close socket. */
|
||
|
close(data_socket);
|
||
|
|
||
|
/* Quit on DOWN command. */
|
||
|
if (down_flag) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
close(listen_socket);
|
||
|
|
||
|
/* Unlink the socket. */
|
||
|
unlink(SOCKET_NAME);
|
||
|
|
||
|
exit(EXIT_SUCCESS);
|
||
|
}
|