/* Daytime Daemon
@2000 Helder Daniel
formato de linha de comando: dtd <maximo de conexoes concorrentes> <porto>
*/
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <signal.h>
#include <sys/stat.h>
#include <time.h>
#include <string.h>
#include <errno.h>
int Numproc=0;
void end_child(int s)
{
/* Suspende a execuçao do processo corrente, ate que um filho especificado
pelo 1º parametro termine. Se este valor for 0 espera por qualquer processo
do mesmo grupo. O 2º parametro indica onde a funçao pode guardar informacao
sobre o estado da termincao do processo especificado no 1º parametro.
O 3º parametro WNOHANG indica que waitpid retorna imediatamente se nenhum
filho esta a terminar ou Zombie. Neste caso, waitpid, retorna zero, se
existir um erro retorna -1, e em qualquer outro caso o PID do filho que terminou.
*/
if (waitpid(0, NULL, WNOHANG)>0) Numproc--;
else signal (SIGCHLD, end_child);
/* Se nao existir nenhum filho a terminar ou Zombie ou se ocorreu um erro com
waitpid sera necessario restabelecer este manipulador
*/
}
void killsocket(int s, char *m)
{
perror(m); /* Imprime mensagem de erro */
shutdown(s, 2); /* Desliga a conexao full-duplex associada com o socket s.
2 -> recusar futuros sends e receives */
exit (-1);
}
void sendinfo(int s, FILE *out)
{
char *buf;
time_t t;
t = time(NULL);
if (t==-1) fprintf(out, "%s\n", strerror(errno));
fprintf(out, "%s", ctime(&t));
fclose (out);
}
main(int argc, char **argv)
{
int port;
int maxproc;
int sock, csock;
int n;
struct sockaddr_in server, client;
int lc= sizeof(client);
FILE *io;
/* Valida linha de comandos
*/
if (argc!=3)
{
puts("formato de linha de comando:\n"
"dtd <maximo de conexoes concorrentes> <porto>");
exit(-1);
}
if (atoi(*(argv+1))<1 || atoi(*(argv+1))>25)
{
puts("Conexoes suportadas 1 - 25.\n");
exit(-1);
}
else maxproc=atoi(*(argv+1));
if (atoi(*(argv+2))<1024 || atoi(*(argv+2))>65535)
{
puts("Portos possiveis: 1024 - 65535\n");
exit(-1);
}
else port=atoi(*(argv+2));
/* cria o socket sock, para internet, orientado para a ligaçao (tipo stream)
*/
if((sock=socket(AF_INET, SOCK_STREAM, 0))==-1) //start server socket TCP socket
{
perror("Impossivel criar socket!");
exit(-1);
}
/* Habilita reutilizaçao do endereço local
(n=1 enable option; n=0 disable option)
*/
n=1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &n, sizeof(n))==-1) //Socker reutilizavel, mais do que um cliente
killsocket (sock, "Impossivel seleccionar opcçoes do socket");
/* Preenche a estrutura server com zeros
*/
memset(&server, 0, sizeof(server));
/* Define o endereço local server
*/
server.sin_family=AF_INET; /* Suporta familia de endereços internet */
server.sin_addr.s_addr=htonl(INADDR_ANY); /* Aceita qualquer endereço de ligaçao */
server.sin_port=htons(port); /* Porto > 1023 e < 65535 */
/* Atribui ao socket sock o endereço local server, o qual identifica o servidor
*/
if (bind(sock, (struct sockaddr *) &server, sizeof(server))==-1)
killsocket (sock, "Impossivel atribuir endereço local ao socket");
/* Activa a fila de espera de coneçoes, para o socket sock, e limita-a a 5 coneçoes
*/
if (listen(sock, 5)==-1) //qeue de 5, nao passa daqui ate que um cliente se conecte
killsocket (sock, "Impossivel reservar fila de coneçoes para o socket");
/* Socket criado com sucesso */
/* Processo corrente lança um filho e termina. O pai do filho passa a ser o init.
Seguidamente o Daemon fecha os canais de comunicaçao com a consola.
Assim cria-se um daemon (em DOS chama-se TSR)
*/
if (fork()!=0) exit(0);
close(stdin);
close(stdout);
/* Define a rotina para tratamento do fim de um filho
*/
signal (SIGCHLD, end_child);
/* Ignora o sinal SIGHUP, ou seja evita terminar o processo corrente se o terminal
que o lançou for fechado ou se o processo que o controla for morto
*/
signal (SIGHUP, SIG_IGN);
/* Ciclo principal
Escuta pedidos e trata-os
*/
for (;;)
{
if (Numproc <= maxproc)
{
/* Retira a primeira conecçao da fila de listen.
accept cria um novo socket com as mesmas propriedades de sock e retorna
um descritor para o novo socket (csock), ou -1 se nao existir nenhuma
conecçao na fila de espera. Em client e guardado o endereco do cliente a servir.
*/
do
{
csock=accept (sock, (struct sockaddr *)&client, &lc);
}
while (csock==-1);
/* Cria filho para atender o pedido
*/
if (csock==-1) sleep (1); /* Erro na abertura do sockect para cliente */
else
{
Numproc++;
switch(fork())
{
/* Filho atende pedido */
case 0:
/* Fecha descritor nao necessario de socket */
close (sock);
/* associa um stream com o descriptor para o cliente */
if ((io = fdopen(csock, "r+"))!=NULL)
{
/* Manipulador */
sendinfo(csock, io);
/* descarrega buffers antes de terminar filho */
fflush (io);
}
/* Termina filho depois de atender o pedido */
exit (0);
/* Erro na criaçao do filho */
case -1:
Numproc--;
close (csock);
break;
/* Se pai fechar csock pois o filho vai atender o pedido */
default:
close(csock);
} /* switch */
} /* else */
} /* if */
} /* for (;;) */
} /* main */
朱moyimi
- 粉丝: 75
- 资源: 1万+
最新资源
- 4353_135543959.html
- C#物联订单仓储综合管理系统源码 物联综合管理系统源码数据库 SQL2008源码类型 WebForm
- 2024年最新敏感词库(7万余条)
- java带财务进销存ERP管理系统源码数据库 MySQL源码类型 WebForm
- java制造业MES生产管理系统源码 MES源码数据库 MySQL源码类型 WebForm
- 基于无人机航拍数据实现的三维场景重建python源代码+文档说明+数据集(高分项目)
- 【重磅,更新!】全国2000-2022年植被指数数据(分辨率30m)
- 包含Qt5Core.dll Qt5Gui.dll Qt5Network.dll Qt5Svg.dll Qt5Widgets.dl
- python3.6 get-pip.py
- python期末大作业基于ResNet的人脸表情识别项目源码+数据集+模型文件(高分项目)
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈