프로그래밍 공부중인데. 의문점이 있어서 글을 올립니다.

LWC3의 이미지

아래 등록한 코드로 소켓 프로그래밍을 공부하고 있는데 궁금한 점이 있어서 글을 올립니다.

아래 서버 프로그램을 실행 시킨 후에 Ctrl+c 를 사용해서 SIGINT 시그널을 발생시키면
init_handler 가 잘 동작합니다. 그런데 telnet 으로 한번 연결 후에는 시그널을 발생 시켜도
init_handler 가 동작하지 않습니다. 왜 accept 이후에는 시그널이 동작하지 않는지요?

그리고 하나더 궁금한 점은 accept 이후에 root@ubuntu:~/work/c/server$ 이 출력되는데요.
부모 프로세스가 종료되어야 커맨드 입력 부분이 출력되는 부분이지 않나요?

알려주시면 감사하겠습니다. ㅎ..;

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/wait.h>
#include<signal.h>
 
#define MYPORT 3490	// the port users will be connecting to
 
#define BACKLOG 10	// how many pending connections queue will hold
 
void sigchld_handler(int s)
{
	while(wait(NULL) > 0);
}
 
void init_handler(int s)
{
	printf("\t init start\n");
}
 
int main(argc, argv)
int argc;
char** argv;
{
	int sockfd, new_fd;	// listen on sock_fd, new connection on new_fd
	struct sockaddr_in my_addr;	// my address information
	struct sockaddr_in their_addr;	// connector's address information
	int sin_size;
	struct sigaction sa, sig_init;
	int yes=1;
	int ret;
 
	if((sockfd=socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		perror("socket");
		return 1;
	}
 
	if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
		perror("setsockopt_reuseaddr");
		return 1;
	}
 
	my_addr.sin_family = AF_INET;			// host byte order
	my_addr.sin_port = htons(MYPORT);	// short, network byte order
	my_addr.sin_addr.s_addr = htonl(INADDR_ANY); // automatically fill with my IP
	// my_addr.sin_addr.s_addr = inet_addr("127.0.0.1");	// manual IP
	bzero(&(my_addr.sin_zero), 8);		// zero the rest of the struct
 
	if(bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
		perror("bind");
		return 1;
	}
 
	if(listen(sockfd, BACKLOG) == -1) {
		perror("listen");
		return 1;
	}
 
	sa.sa_handler = sigchld_handler;	// reap all dead processes
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = SA_RESTART;
	if(sigaction(SIGCHLD, &sa, NULL) == -1) {
		perror("sigaction");
		return 1;
	}
 
	sig_init.sa_handler = init_handler;
	sigemptyset(&sig_init.sa_mask);
	if(sigaction(SIGINT, &sig_init, NULL) == -1) {
		perror("sigaction_init");
		return 1;
	}
 
	while(1) {	// main accept() loop
		sin_size = sizeof(struct sockaddr_in);
		if((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) {
			perror("accept");
			continue;
		}
		printf("server: got connection from %s\n", inet_ntoa(their_addr.sin_addr));
 
		ret = fork();
 
		if(0==ret) {	// this is parent process
			printf("this is parent process\n");
		}else{	// this is child process
			printf("this is child process\n");
			close(sockfd);	// child doesn't need the listener
			if(send(new_fd, "Hello, world!\n", 14, 0) == -1)
				perror("send");
			close(new_fd);
			printf("child process exit\n");
			return 1;
		}
		printf("\t process : %d, parent process : %d, try to close\n", getpid(), getppid());
		close(new_fd);	// parent doesn't need this
	}
 
	return 0;
}

shint의 이미지

- Ctrl + 모든 키를 입력해보세요. ㅇ_ㅇ;; Ctrl + Z, Ctrl + \ 등등...
- Unix System Programming for SVR4 책에 자세히 나와있습니다. 책보고 따라해보시면 편합니다.
- 터미널 명령어도 몇개 되네요. ㅇ_ㅇ;;
- 모든 변수와 함수를 검색해보겠습니다.
- 각 함수에 인자값. 리턴값. 오류값을 확인해보겠습니다.
- select() 도 있습니다.

----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

익명 사용자의 이미지

        if(0!=ret) {    // this is parent process                              
            printf("this is parent process\n");                                
        }else{  // this is child process                                       
            printf("this is child process\n");                                 
            close(sockfd);  // child doesn't need the listener                 
            if(send(new_fd, "Hello, world!\n", 14, 0) == -1)                   
                perror("send");                                                
            close(new_fd);                                                     
            printf("child process exit\n");                                    
            return 1;                                                          
        }

위의 코드를 다음과 같이 고쳐보세요.

    if (0 == ret) { // this is a child process.
        printf("this is child process\n");                                 
        close(sockfd);  // child doesn't need the listener                 
        if(send(new_fd, "Hello, world!\n", 14, 0) == -1)                   
             perror("send");                                                
        close(new_fd);                                                     
        printf("child process exit\n");                                    
        return 1;                                                          
    }
    else {
        printf("this is parent process\n");
    }

(0 == ret)은 부모 프로세스가 아니라 자식프로세스입니다.

익명 사용자의 이미지

본문을 잘못 복사&붙여넣기 했네요.
다시 말하자면,

		if(0==ret) {	// this is parent process
			printf("this is parent process\n");
		}else{	// this is child process
			printf("this is child process\n");
			close(sockfd);	// child doesn't need the listener
			if(send(new_fd, "Hello, world!\n", 14, 0) == -1)
				perror("send");
			close(new_fd);
			printf("child process exit\n");
			return 1;
		}

위의 코드를 다음과 같이 고쳐보세요.
    if (0 == ret) { // this is a child process.
        printf("this is child process\n");                                 
        close(sockfd);  // child doesn't need the listener                 
        if(send(new_fd, "Hello, world!\n", 14, 0) == -1)                   
             perror("send");                                                
        close(new_fd);                                                     
        printf("child process exit\n");                                    
        return 1;                                                          
    }
    else {
        printf("this is parent process\n");
    }

to shint,
도와주고 싶어하는 마음은 알겠으나, 질문을 이해하기 위해 5~10분정도의 시간도 투자하기 아깝다면
답변을 안주는게 낫습니다. 가볍게 아님말고 식의 답변보다, 진지한답변이 질문자에게 도움이 됩니다.

LWC3의 이미지

덕분에 돌아가지 않고 시간을 아꼈습니다. 감사합니다. ^^

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.