#include "common.h"

void sigchld_handler(int sig) 
{
    while (waitpid(-1, 0, WNOHANG) > 0);
    return;
}

typedef void (*sighandler_t) (int sig) ;

void Signal(int sig, sighandler_t handler){
    struct sigaction sa;
    sa.sa_handler = sigchld_handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART;  // 确保被信号中断的系统调用自动重启
    sigaction(SIGCHLD, &sa, NULL);
}

//工作函数
void toggle(int conn_sock,int hit) 
{
    size_t n; int i,no=0;
    char buf[MAXLINE]; 

    printf("第%d个客户通信开始\n",hit);
    while((n =recv(conn_sock, buf, MAXLINE,0))> 0) {
	printf("toggle服务器收到第%d个客户第%d个消息,长度为%d字节\n", hit,++no,(int)n);

        for(i=0; i<n; i++)
            if(isupper(buf[i])) 
                buf[i]=tolower(buf[i]);
            else if(islower(buf[i]))
                buf[i]=toupper(buf[i]);
               
	send (conn_sock, buf, n, 0);
    }
    printf("第%d个客户通信结束\n",hit);
}

int main(int argc, char **argv) 
{
    int listen_sock, conn_sock, port; 
    struct sockaddr_in clientaddr; 
    struct hostent *hp;
    char *haddrp;
    int hit;
        
    socklen_t clientlen=sizeof(struct sockaddr_in);

    if (argc != 2) {
	    fprintf(stderr, "usage: %s <port>\n", argv[0]);
	    exit(1);
    }
    port = atoi(argv[1]);

    //设置SIGHLD的信号处理函数，用于收割结束的子进程
    Signal(SIGCHLD, sigchld_handler);
    
    listen_sock = open_listen_sock(port);
    
    if( listen_sock==-1) {
    	printf("端口号%d繁忙\n",port);
    	exit(1);
    }
    
    for(hit=1; ; hit++) {
        conn_sock = accept(listen_sock, (SA *) &clientaddr, &clientlen);

            /* determine the domain name and IP address of the client */
        hp = gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr, 
                sizeof(clientaddr.sin_addr.s_addr), AF_INET);
        haddrp = inet_ntoa(clientaddr.sin_addr);
        printf("server connected to %s (%s)\n", hp->h_name, haddrp);

        if (fork() == 0) { 
            close(listen_sock);     /* Child process closes its listening socket */
            toggle(conn_sock,hit);    /* Child process services client */
            close(conn_sock);     /* Child process closes connection with client */
            exit(0);                /* Child process exits */
        }
        close(conn_sock);         /* Parent closes connected socket (important!) */
    }
}
