2013-02-16 3 views
2

이것은 강의 목적을위한 기본적인 TCP 서버 구현입니다. 할 오류나 개선이 있습니까? 어떤 제안이라도 환영합니다! 난 단지 의심의 여지가 간단한 TCP 서버

:

signal(SIGCHLD, SIG_IGN); 

는 zoombie - 자식 프로세스를 방지하기 위해 사용하는 전화인가?

#include <netinet/in.h> 
#include <sys/socket.h> 
#include <netdb.h> 

#include <sys/signal.h> 

#include <unistd.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 

#define BACKLOG 5 
#define MAXSIZE 1024 //max-bytes for read-buffer 

void main(){ 

int sock_ds, ret, length; 
int acc_ds; //Accept socket descriptor 

struct sockaddr_in addr; //this addres 
struct sockaddr rem_addr; //remote address (generic) 

char buff[MAXSIZE]; 

sock_ds = socket(AF_INET, SOCK_STREAM, 0); // => TCP 

bzero((char *)&addr, sizeof(addr)); //reset struct 
addr.sin_family = AF_INET; 
addr.sin_port = htons(25000); 
addr.sin_addr.s_addr = INADDR_ANY; 
ret = bind(sock_ds, &addr, sizeof(addr)); 
if(ret == -1){ 
    perror("Binding error"); 
    exit(1); 
} 

ret = listen(sock_ds, BACKLOG); // backlog queue 
    if(ret == -1){ 
    perror("Listen error"); 
    exit(1); 
} 

length = sizeof(rem_addr); 
signal(SIGCHLD, SIG_IGN); //zombie children management 

/*Busy-waiting (server) and concurrency */ 
while(1){ 

    /*Repeat until success*/ 
    while(acc_ds = accept(sock_ds, &rem_addr, &length) == -1){ 

     if(fork() == 0){ //child-process 

      close(sock_ds); //unused from child 
      do{ 
       read(acc_ds, buff, MAXSIZE); 
       printf("Message from remote host:&s\n", buff); 

      }while(strcmp(buff, "quit") == 0); 
      /*Transimission completed: server response */ 
      write(acc_ds, "Reading Done", 10); 
      close(acc_ds); //socket closed 
      exit(0); //exiting from child 
     } 
     else{ 
      close(acc_ds); //unused from parent 
     } 
    } 
} 

}

+0

네, 그 아이디어는 맞지만 대신'sigaction'을 사용해야합니다. 그것은 같은 목적을 달성하지만 신호를 다루는 현대적인 방법입니다. http://linux.die.net/man/2/sigaction – shanet

답변

2

네, SIGCHLD를 무시하기위한 것입니다 정확히입니다. TLPI에서 :

There is a further possibility for dealing with dead child processes. Explicitly setting the disposition of SIGCHLD to SIG_IGN causes any child process that subsequently terminates to be immediately removed from the system instead of being converted into a zombie.

이것은 UNIX 구현에서 표준입니다. main

3
  1. 반환 유형은 int 없습니다. 그것은해야한다. EXIT_SUCCESS 또는 EXIT_FAILURE을 반환하십시오.
  2. socket()의 결과는 확인되지 않습니다. 또는 bind이 실패하지만 perror()은 실제 오류 대신 "유효하지 않은 인수"를 알립니다.
  3. 반환 값 read()은 검사 할 때 인쇄 할 때 정의되지 않은 동작을 트리거 할 수 있습니다.
  4. &s 형식이 지정되어 있지 않습니다. %s이어야합니다.
  5. %s은 널로 끝나는 문자열을 예상합니다. 이는 코드에서 보장하지 않습니다 (포인트 # 3 참조). strcmp()도 쓸모가있을 수 있습니다.

SIGCHLD에 대해서는 @cnicutar가 이미 거기에 추가 할 것이 없다고 친절하게 대답했습니다.

희망이 있습니다. 행운을 빕니다!

+2

안녕하세요, 모든 것을 잡는 멋진 직장입니다. – cnicutar

0

어떻게 작동하는지 알아야합니다. 그래서, 나는 "간단한 tcp-server"를 봤는데,이 작은 프로그램을 발견하고 gcc -Wall과 주석으로 더 행복해 지도록 코드를 수정했다. 여기에 함께 넣어 무엇입니까 :

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <errno.h> 
#include <unistd.h> 

#include <signal.h> 

#include <netinet/in.h> 
#include <sys/socket.h> 
#include <netdb.h> 

#include <sys/wait.h> 
#include <sys/types.h> 
#include <sys/ptrace.h> 


#define BACKLOG 5 
#define MAXSIZE 1024 //max-bytes for read-buffer 

#define PORT 25000 

/****************************************************************/ 
int main() { 

    int sock_ds, ret; unsigned int length; 
    int acc_ds; //Accept socket descriptor 

    struct sockaddr_in addr; //this address 
    struct sockaddr rem_addr; //remote address (generic) 

    char buff[MAXSIZE+1]; 

    if (!(sock_ds = socket(AF_INET, SOCK_STREAM, 0))) perror("socket call failed"); // => TCP 

    bzero((char *)&addr, sizeof(addr)); //reset struct 
    addr.sin_family = AF_INET; 
    addr.sin_port = htons(PORT); 
    addr.sin_addr.s_addr = INADDR_ANY; 
    ret = bind(sock_ds, (struct sockaddr *)&addr, sizeof(addr)); 
    if (ret == -1) { 
    perror("Binding error"); 
    exit(EXIT_FAILURE); 
    } 

    ret = listen(sock_ds, BACKLOG); // backlog queue 
    if (ret == (-1)) { 
    perror("Listen error"); 
    exit(EXIT_FAILURE); 
    } 

    length = sizeof (rem_addr); 
    // sigaction(SIGCHLD, SA_NOCLDWAIT); //zombie children management 

    /*Busy-waiting (server) and concurrency */ 
    while (1) { 
    fprintf(stderr, "[Waiting for client %d]\n", getpid()); 

    /*Repeat until success*/ 
    while ((acc_ds = accept(sock_ds, &rem_addr, &length)) == -1) { 
     fprintf(stderr, "[Accepted from client %d]\n", getpid()); 

     if (fork() == 0) { //child-process 
     close(sock_ds); //unused from child 
     fprintf(stderr, "[Reading from client %d]\n", getpid()); 
     while (read(acc_ds, buff, MAXSIZE)) { 
      buff[MAXSIZE]='\0'; 
      printf("Message from remote host:%s\n", buff); 
      fflush(stdout); 
      if (strncmp (buff, "quit", 5) == 0) break; 
     } 

     /*Transmission completed: server response */ 

     if (write(acc_ds, "Reading Done", 10)) fprintf(stderr, "failed write\n"); 
     close(acc_ds); //socket closed 
     exit(EXIT_SUCCESS); //exiting from child 
     } 
     else{ 
     close(acc_ds); //unused from parent 
     } 
    } 
    } 
    return EXIT_SUCCESS; 
} 

두 가지 문제가 있습니다. 첫 번째는 GNU 리눅스 GCC는 두 번째 I 포트 25000에 텔넷 및 몇 가지를 입력 할 때 수신 한, 아무것도 이제까지 반향되지 않은 것입니다

sigaction(SIGCHLD, SA_NOCLDWAIT); //zombie children management 

tcp-server2.c: In function ‘main’: tcp-server2.c:53:3: warning: passing argument 2 of ‘sigaction’ makes pointer from integer without a cast [enabled by default] In file included from tcp-server2.c:7:0: /usr/include/signal.h:267:12: note: expected ‘const struct sigaction * restrict’ but argument is of type ‘int’ tcp-server2.c:53:3: error: too few arguments to function ‘sigaction’ In file included from tcp-server2.c:7:0: /usr/include/signal.h:267:12: note: declared here

동의를 거부한다는 것입니다. 그래서 서버가 작동하지 않는 것 같습니다. 결코 고객으로부터 받아 들여지지 않습니다.

지금은 다른 곳에서 프로그래밍 예제를 고를 수는 있지만 여기서 간단히보고해야한다고 생각 했으므로 가장 간단한 tcp 서버가 올바르게 게시됩니다.

관련 문제