Skip to content

Instantly share code, notes, and snippets.

@abaduser
Created October 2, 2023 18:39
Show Gist options
  • Save abaduser/728be35dd175ae1ba570fe25d5497e1c to your computer and use it in GitHub Desktop.
Save abaduser/728be35dd175ae1ba570fe25d5497e1c to your computer and use it in GitHub Desktop.
tcp shared mem writer
#include <iostream>
#include <algorithm>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <thread>
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <signal.h>
#ifdef DEBUG
#define HOST htonl(INADDR_LOOPBACK)
#else
#define HOST INADDR_ANY
#endif
const int PORT = 65432;
const int BUFFER_SIZE = 1024;
const key_t SHM_KEY = 12345;
void daemonize() {
pid_t pid = fork();
if (pid > 0) {
exit(0); // Parent exits
}
chdir("/");
setsid();
umask(0);
pid = fork();
if (pid > 0) {
exit(0); // Parent exits
}
#ifdef DEBUG
std::cout << "Daemonized process ID: " << getpid() << std::endl;
#endif
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
}
void handle_client(int client_fd) {
int shm_id = -1;
char* ptr = nullptr;
int connection_attempts = 0;
char buffer[BUFFER_SIZE];
while (true) {
if (shm_id == -1) {
shm_id = shmget(SHM_KEY, 1, 0666); // Get the shared memory segment
if (shm_id == -1) {
connection_attempts++;
if (connection_attempts >= 10) {
send(client_fd, "Max attempts reached. Closing connection.\n", 41, 0);
break;
}
send(client_fd, "Shared memory does not exist. Trying again in 2 seconds...\n", 60, 0);
sleep(2);
continue;
}
ptr = (char*) shmat(shm_id, NULL, 0);
if (ptr == (char*) -1) {
#ifdef DEBUG
std::cerr << "Error attaching to shared memory." << std::endl;
#endif
ptr = nullptr;
}
connection_attempts = 0;
}
ssize_t bytes_read = recv(client_fd, buffer, BUFFER_SIZE - 1, 0); // Reduced buffer size by 1 for null termination
if (bytes_read <= 0) { // Check for errors or client disconnect
if (bytes_read < 0) {
#ifdef DEBUG
std::cerr << "Error reading from client. Closing connection." << std::endl;
#endif
}
break;
}
buffer[bytes_read] = '\0';
std::string data(buffer);
data.erase(std::remove_if(data.begin(), data.end(), ::isspace), data.end());
if (data == "exit") {
break;
}
if (ptr && (data == "0" || data == "1")) {
if (data == "0") {
*ptr = 0;
} else if (data == "1") {
*ptr = 1;
}
// Check for errors when sending
ssize_t bytes_sent = send(client_fd, "Value written to shared memory.\n", 33, 0);
if (bytes_sent < 0) {
#ifdef DEBUG
std::cerr << "Error sending to client. Closing connection." << std::endl;
#endif
break;
}
} else {
send(client_fd, "Invalid input. Please send 0 or 1.\n", 36, 0);
}
}
if (ptr) {
shmdt(ptr);
}
close(client_fd);
}
int main() {
daemonize(); // Daemonize
signal(SIGCHLD, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd == -1) {
return 1;
}
sockaddr_in address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = HOST;
address.sin_port = htons(PORT);
if (bind(server_fd, (struct sockaddr*)&address, sizeof(address)) < 0) {
return 1;
}
if (listen(server_fd, 10) < 0) {
return 1;
}
while (true) {
int client_fd = accept(server_fd, nullptr, nullptr);
if (client_fd < 0) {
continue;
}
std::thread client_thread(handle_client, client_fd);
client_thread.detach();
}
close(server_fd);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment