Вот базовый пример демона в C, который прослушивает указанный номер порта. Я написал это как простой пример, указывающий на возможный путь решения. Так что, пожалуйста, имейте в виду, что это не что-то готовое к использованию в производстве. Конечно, вещи с MySQL не включены.
Я предполагаю, что приведенные ниже действия должны быть выполнены на некоторых ОС на базе Linux.
После компиляции:
gcc portd.c -o portd
это можно просто запустить как
./portd
Затем вы можете проверить это, используя telnet:
telnet localhost 8000
введите простую строку, например, "test" и нажмите ввод, затем проверьте файл журнала демона в /tmp/portd.log
Вот код (portd.c):
/**
* Simple daemon bind to a specified port example
*
* @author Mykhailo Stadnyk <mikhus@smart-ip.net>
* @version 1.0
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <time.h>
#define DEFAULT_RUNNING_DIR "/tmp"
#define DEFAULT_PID_FILE "/tmp/portd.pid"
#define DEFAULT_LOG_FILE "/tmp/portd.log"
#define DEFAULI_LISTEN_PORT 8000
/**
* Logging daemon activity
*/
void log_message( char *filename, const char *message) {
FILE *logfile;
logfile = fopen( filename, "a");
if (!logfile) {
return;
}
fprintf( logfile,"%s\n", message);
fclose( logfile);
}
/**
* Signals handler (kill -HUP `cat /tmp/portdaemon.pid`, kill `cat /tmp/portdaemon.pid`)
*/
void signal_handler( int sig) {
switch( sig){
case SIGHUP: {
log_message( DEFAULT_LOG_FILE, "portd: hangup signal catched, restarting...\n");
break;
}
case SIGTERM: {
log_message( DEFAULT_LOG_FILE, "portd: terminate signal catched, terminating...\n");
exit( 0);
break;
}
}
}
/**
* Daemonizing the application
*/
void daemonize( char *pidfile) {
int i, lfp;
char str[10];
if (pidfile)
if(getpid() == 1) {
return; /* already a daemon */
}
i = fork();
if (i < 0) {
exit( 1); /* fork error */
}
if (i > 0) {
printf( "Portd daemon started, PID: %d\n", i);
exit( 0); /* parent exits */
}
/* child (daemon) continues */
setsid(); /* obtain a new process group */
for (i = getdtablesize(); i >= 0; --i) {
close( i); /* close all descriptors */
}
i = open( "/dev/null", O_RDWR); dup( i); dup( i); /* handle standart I/O */
umask(027); /* set newly created file permissions */
chdir( DEFAULT_RUNNING_DIR); /* change running directory */
lfp = open( pidfile, O_RDWR|O_CREAT, 0640);
if (lfp < 0) {
exit( 1); /* can not open */
}
if (lockf( lfp, F_TLOCK,0) < 0) {
exit( 0); /* can not lock */
}
/* first instance continues */
sprintf( str,"%d\n",getpid());
write( lfp, str, strlen( str)); /* record pid to lockfile */
signal( SIGCHLD, SIG_IGN); /* ignore child */
signal( SIGTSTP, SIG_IGN); /* ignore tty signals */
signal( SIGTTOU, SIG_IGN);
signal( SIGTTIN, SIG_IGN);
signal( SIGHUP, signal_handler); /* catch hangup signal */
signal( SIGTERM, signal_handler); /* catch kill signal */
}
void error( const char *msg) {
log_message( DEFAULT_LOG_FILE, msg);
perror( msg);
exit( 1);
}
int listen_socket( int portno) {
int sockfd;
struct sockaddr_in serv_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
error("ERROR opening socket");
}
bzero((char *) &serv_addr, sizeof( serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons( portno);
if (bind( sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
error("ERROR on binding");
}
listen( sockfd,5);
return sockfd;
}
// main programm code
int main( int argc, char **argv) {
// starting daemon
daemonize( (char*) DEFAULT_PID_FILE);
// bind to port (listen the specific port on all network interfaces)
int sock_listen = listen_socket( DEFAULI_LISTEN_PORT);
while (1) {
// create read/write socket for client
int sock_client;
socklen_t clilen;
struct sockaddr_in cli_addr;
clilen = sizeof( cli_addr);
sock_client = accept( sock_listen, (struct sockaddr *) &cli_addr, &clilen);
if (sock_client < 0) {
// nobody connected?
sleep( 1);
continue;
}
// read buffer
char buffer[256];
bzero( buffer, 256);
// read the data from socket to buffer
if (read( sock_client, buffer, 255) < 0) {
// client was connected but we failed to read the message from him
log_message( DEFAULT_LOG_FILE, "Can not read data from client!");
close( sock_client);
continue;
}
// Voila! client connected - data recieved and saved to buffer variable
// now we can do something with data from client
// here we just put data in a logfile and close the connection
log_message( DEFAULT_LOG_FILE, (char *) buffer);
close( sock_client);
}
return 0;
}