2017-05-22 1 views
0

기본 응용 프로그램이 실행되는 응용 프로그램을 가지고 있고 주 응용 프로그램과주고받을 수있는 데몬을 만들고 싶습니다. 둘 다 서버와 클라이언트로 작동 할 수 있습니다.그 중 하나가 데몬 인 2 개의 프로세스 사이에서 소켓 통신을 수행해야합니다.

서버 코드 :

pthread_t t1; 
pthread_t t2; 

int main() 
{ 
int sockfd;//to create socket 
int newsockfd;//to accept connection 
pthread_attr_t attr; 
pthread_attr_init(&attr); 
pthread_attr_setstacksize(&attr,1024*1024); 

int status; 
printf("Creating Threads1::\n"); 
status=pthread_create(&t1,&attr,(void*)&call_server_thread,NULL); 
if(status!=0){ 
    printf("Failed to create Thread1 with Status:%d\n",status); 
} 

/* 
printf("Creating Threads2::\n"); 
status=pthread_create(&t2,&attr,(void*)&call_client_thread,NULL); 
if(status!=0){ 
    printf("Failed to create Thread2 with Status:%d\n",status); 
} 
*/ 

pthread_join(t1,NULL); 
//pthread_join(t2,NULL); 

return 0; 

} 

void call_server_thread() 
{ 
//create socket 
int sockfd;//to create socket 
int newsockfd;//to accept connection 

struct sockaddr_in serverAddress;//server receive on this address 
struct sockaddr_in clientAddress;//server sends to client on this address 

int n,exec_sec=3; 
char msg[MAXSZ]; 
int clientAddressLength; 
int pid; 
sockfd=socket(AF_INET,SOCK_STREAM,0); 
//initialize the socket addresses 
memset(&serverAddress,0,sizeof(serverAddress)); 
serverAddress.sin_family=AF_INET; 
serverAddress.sin_addr.s_addr=htonl(INADDR_ANY); 
serverAddress.sin_port=htons(PORT); 

//bind the socket with the server address and port 
bind(sockfd,(struct sockaddr *)&serverAddress, sizeof(serverAddress)); 

//listen for connection from client 
listen(sockfd,5); 

while(1) 
{ 
    //parent process waiting to accept a new connection 
    printf("\n*****server waiting for new client connection:*****\n"); 
    clientAddressLength=sizeof(clientAddress); 
    newsockfd=accept(sockfd,(struct 
    sockaddr*)&clientAddress,&clientAddressLength); 
    // printf("connected to client: 
    %d\n",inet_ntoa(clientAddress.sin_addr)); 

    //child process is created for serving each new clients 
    pid=fork(); 
    if(pid==0)//child process rec and send 
    { 
     //rceive from client 
     while(1) 
     { 
      n=recv(newsockfd,msg,MAXSZ,0); 
      if(n==0) 
      { 
       close(newsockfd); 
       break; 
      } 
      msg[n]='\0'; 
      send(newsockfd,msg,n,0); 

      printf("Receive and set:%s\n",msg); 
      printf("Server Thread will sleep for %d seconds\n",exec_sec); 
      sleep(exec_sec); 
     }//close interior while 
     exit(0); 
    } 
    else 
    { 
     close(newsockfd);//sock is closed BY PARENT 
    } 
    printf("Server Thread will sleep for %d seconds\n",exec_sec); 
    sleep(exec_sec); 
}//close exterior while 

} 

클라이언트 코드 ::

int daemonize(char* name, char* path, char* outfile, char* errfile, char* 
infile) 
{ 
if(!path) { path="~/CODE/PLATFORM/"; } 
if(!name) { name="medaemon"; } 
if(!infile) { infile="/dev/null"; } 
if(!outfile) { outfile="/dev/null"; } 
if(!errfile) { errfile="/dev/null"; } 
//printf("%s %s %s %s\n",name,path,outfile,infile); 
pid_t child; 
//fork, detach from process group leader 
if((child=fork())<0) { //failed fork 
    fprintf(stderr,"error: failed fork\n"); 
    exit(EXIT_FAILURE); 
} 
if (child>0) { //parent 
    exit(EXIT_SUCCESS); 
} 
if(setsid()<0) { //failed to become session leader 
    fprintf(stderr,"error: failed setsid\n"); 
    exit(EXIT_FAILURE); 
} 

//catch/ignore signals 
signal(SIGCHLD,SIG_IGN); 
signal(SIGHUP,SIG_IGN); 

//fork second time 
if ((child=fork())<0) { //failed fork 
    fprintf(stderr,"error: failed fork\n"); 
    exit(EXIT_FAILURE); 
} 
if(child>0) { //parent 
    exit(EXIT_SUCCESS); 
} 

//new file permissions 
umask(0); 
//change to path directory 
chdir(path); 

//Close all open file descriptors 
int fd; 
for(fd=sysconf(_SC_OPEN_MAX); fd>0; --fd) 
{ 
    close(fd); 
} 

//reopen stdin, stdout, stderr 
stdin=fopen(infile,"r"); //fd=0 
stdout=fopen(outfile,"w+"); //fd=1 
stderr=fopen(errfile,"w+"); //fd=2 

//open syslog 
openlog(name,LOG_PID,LOG_DAEMON); 
return(0); 
} 



int main() 
{ 
int sockfd;//to create socket 

struct sockaddr_in serverAddress;//client will connect on this 

int n,res; 
char msg1[MAXSZ]; 
char msg2[MAXSZ]; 

//create socket 
sockfd=socket(AF_INET,SOCK_STREAM,0); 
//initialize the socket addresses 
memset(&serverAddress,0,sizeof(serverAddress)); 
serverAddress.sin_family=AF_INET; 
serverAddress.sin_addr.s_addr=inet_addr(SERVER_IP); 
serverAddress.sin_port=htons(PORT); 

//client connect to server on port 
connect(sockfd,(struct sockaddr *)&serverAddress,sizeof(serverAddress)); 
//send to sever and receive from server 

if((res=daemonize("mydaemon","~/CODE/PLATFORM",NULL,NULL,NULL)) != 0) { 
    fprintf(stderr,"error: daemonize failed\n"); 
    exit(EXIT_FAILURE); 
} 

while(1) 
{ 
    printf("\nEnter message to send to server:\n"); 
    //fgets(msg1,MAXSZ,stdin); 

    memcpy(msg1,"INDRA",strlen("INDRA")); 

    if(msg1[0]=='#') 
     break; 

    n=strlen(msg1)+1; 
    send(sockfd,msg1,n,0); 

    n=recv(sockfd,msg2,MAXSZ,0); 

    printf("Receive message from server::%s\n",msg2); 
    sleep(3); 
} 

return 0; 
} 

내가 할 경우 클라이언트 코드는 다음 잘 통신 작동하지 daemonize는 설립했다하지만 순간 내가 API를 호출 daemonize()daemonize이 프로세스에서 서버 응용 프로그램은 클라이언트 코드에서 모든 통신을 수신하지 않습니다.

without daemon output: 

    [[email protected] Process]$ ./a.out 
    Creating Threads1:: 

    *****server waiting for new client connection:***** 
    Server Thread will sleep for 3 seconds 
    Receive and set:INDRA 
    Server Thread will sleep for 3 seconds 

    *****server waiting for new client connection:***** 
    Receive and set:INDRA 
    Server Thread will sleep for 3 seconds 
    Receive and set:INDRA 
    Server Thread will sleep for 3 seconds 
    Receive and set:INDRA 
    Server Thread will sleep for 3 seconds 
    Receive and set:INDRA 

with daemon output :: 

Creating Threads1:: 

*****server waiting for new client connection:***** 
Server Thread will sleep for 3 seconds 

*****server waiting for new client connection:***** 
^C 

여기에서 나는 무엇을 놓치고 있습니까? 당신이 당신의 소켓을 포함한 모든 설명을 닫는 daemonize를 호출하기 전에 이것에 어떤 도움을 매우 극명하게 될 것이다

..

+0

서식 지정/들여 쓰기 ............ – ThingyWotsit

+0

'n = recv (newsockfd, msg, MAXSZ, 0);' 'msg [n] ='\ 0 ';' 모든 MAXSZ 문자가 수신되면 범위를 벗어난 쓰기이므로 UB가됩니다. 버퍼를 오버 사이즈 (MAXSZ + 1)하거나 크기를 줄입니다 (MAXSZ-1). – ThingyWotsit

답변

3

당신은 클라이언트의 소켓 연결을 엽니 다.

이후에 소켓 연결 을 열면 클라이언트 프로세스를 "데몬 시즈"합니다.


더 많은 오류 검사를 추가해야 실제로 오류가 인쇄됩니다. 클라이언트의 sendrecv 호출은 모두 -1을 반환하고 errno을 적절하게 설정했을 것입니다.

특수 플래그를 설정해야하는 경우가 아니면 sendrecv 대신 writeread을 사용하는 것이 좋습니다.

+0

검토해 주셔서 감사합니다. 나는 그 오류를 간과했다. 나는 소켓 생성 순서를 바꾸었지만 여전히 같은 문제가 발생했다. 서버는 데몬 화 된 클라이언트를 가져올 수 없다. 주요한 문제는 데몬입니다. 해결책을 찾기가 더 좋습니다. 데몬이 없으면 제대로 작동합니다. – Indra

+0

아래 코드 부분을 주석 처리하고 클라이언트 코드를 daemonize하는 중입니다. 이것은 서버 소켓 파일 기술자조차 닫고 있었다. 이제 원활하게 작동합니다 .. /* for (fd = sysconf (_SC_OPEN_MAX); fd> 0; --fd) { close (fd); } * / – Indra

관련 문제