다시 질문입니다...accetp시에

yurina의 이미지

	while(1)
	{
		clilen = sizeof(clientaddr);

		_debug(_fl, " SIGNAL WAIT\n");
		rtn 	= sigwaitinfo(&set, &si);

		/*------------------------------------------------------*/
		/*	receive rts					*/
		/*------------------------------------------------------*/
		if(rtn = SIGRTMIN)
		{
			resockfd = si.si_fd;

			if(resockfd == sockfd)
			{
				_debug(_fl, "accept \n");
	
				clilen = sizeof(clientaddr);
			
				sockfd = accept(fd, (struct sockaddr *)&clientaddr, &clilen);
				if(sockfd < 0)
				{
					_debug(_fl, "Accept error\n");
					return -1;
				}
			
				_debug(_fl, "======== step 1 =========\n");
				setup_sigio(sockfd);
				_debug(_fl, "======== step 2 =========\n");
			}
			else
			{
				_debug(_fl, "==================== step 3 ==========\n");
				memset(&message, 0x00, SZ_MESSAGE);
				
				if(read(resockfd, &message, SZ_MESSAGE) <= 0)
				{
					_debug(_fl, "disconnect \n");
					continue;
				}

			
				_debug(_fl, "[%.2s][%.16s/%.10s][%c][%c]\n",
					message.option, message.user_id,
					message.user_name, message.user_sex,
					message.categorize1);
			}
		}
	}
	




/*-----------------------------------------------------------------------*/
/*	setting socket fd						 */
/*-----------------------------------------------------------------------*/
int	setup_sigio(int fd)
{
	if(fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC) < 0)
	{
		_debug(_fl, "Couldn't setup nonblocking io %d\n", fd);
		return -1;
	}

	if(fcntl(fd, F_SETSIG, SIGRTMIN) < 0)
	{
		_debug(_fl, "Couldn't set signal %d on %d\n", SIGRTMIN, fd);
		return -1;
	}   

	/*----------------------------------------------*/
	/* overflow에 대비하여 				*/
	/* socket 하나당 대기열에 하나만 들어갈수 있도록*/
	/*----------------------------------------------*/
	if(fcntl(fd, F_SETAUXFL, O_ONESIGFD) < 0)
	{
		_debug(_fl, "Couldn't set one signal\n");
		return -1;
	}

	if(fcntl(fd, F_SETOWN, getpid()) < 0)
	{
		_debug(_fl, "Couldn't set owner %d on %d\n", getpid(), fd);
		return -1;
	}

	return 0;
}

클라이언트 소스입니다.

/*-----------------------------------------------------------------------*/
/* File 	: test_client.c						 */
/* Name 	: Lee Moon Sun						 */
/* Date		: 2004. 04. 21						 */
/*-----------------------------------------------------------------------*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>

#include <map>
#include <vector>

using namespace std;

#include "../../include/damo_header.h"

int main(int argc, char **argv)
{
    int sockfd;
    int clilen;
    int state, i=0;
    char buff[20];

    struct sockaddr_in 	serveraddr;
    struct MESSAGE 	message;

    if(argc < 2)
    {
    	printf("usage : ./demo_client [port]\n");
	exit(1);
    }

    _opendebug("damo_chat");

    clilen = sizeof(serveraddr);
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket error : ");
        exit(0);
    }

    bzero(&serveraddr, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    serveraddr.sin_port = htons(atoi(argv[1]));

    if(connect(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
    {
    	_debug(_fl, " connect error[%d]\n", errno);
	exit(1);
    }

    memset(&message, 0x00, SZ_MESSAGE);
    memcpy(message.option, "02", 2);
    memcpy(message.user_id, "yurina", 6);
    memcpy(message.user_name, "이문선", 6);
    message.user_sex 	= 'F';
    message.secure_flag = 'I';
    message.categorize1 = '0';
    message.categorize2 = '1';
    message.room_num 	= 200;
    message.secret_flag = '1';
    strcpy(message.room_name, "문선이 방이당");
    message.max_num 	= 0;
    message.password	= 0;

    write(sockfd, &message, SZ_MESSAGE);
    memset(&buff, 0x00, sizeof(buff));
    read(sockfd, buff, sizeof(buff));
    _debug(_fl, "buff[%s]\n", buff);
    
    /*--------------------------------------*/

    memset(&message, 0x00, SZ_MESSAGE);
    memcpy(message.option, "03", 2);
    memcpy(message.user_id, "yurina99", 8);
    memcpy(message.user_name, "이문숙", 6);
    message.user_sex 	= 'F';
    message.secure_flag = 'I';
    message.categorize1 = '0';
    message.categorize2 = '1';
    message.room_num 	= 200;
    message.secret_flag = '1';
    strcpy(message.room_name, "문선이 방이당");
    message.max_num 	= 0;
    message.password	= 0;

    write(sockfd, &message, SZ_MESSAGE);
    memset(&buff, 0x00, sizeof(buff));
    read(sockfd, buff, sizeof(buff));
    _debug(_fl, "buff[%s]\n", buff);

    /*--------------------------------------*/
    /*
    memset(&message, 0x00, SZ_MESSAGE);
    memcpy(message.option, "02", 2);
    memcpy(message.user_id, "yurina00", 6);
    memcpy(message.user_name, "이문경", 6);
    message.user_sex = 'F';
    message.secure_flag = 'I';
    message.categorize1 = '0';

    write(sockfd, &message, SZ_MESSAGE);
    memset(&buff, 0x00, sizeof(buff));
    read(sockfd, buff, sizeof(buff));
    _debug(_fl, "buff[%s]\n", buff);
    */
    /*--------------------------------------*/

    close(sockfd);
    _closedebug();
}
/*-----------------------------------------------------------------------*/
/* End of Program							 */
/*-----------------------------------------------------------------------*/

위와 같이 RTS를 사용하여 프로그램을 만들었습니다.
client 에서 connect시에 accept하는 구문을 타고
write하면 else구문을 타는데..

<1078><00:05:20:460><main_process><99> SIGNAL WAIT
<1078><00:05:27:320><main_process><111> accept
<1078><00:05:27:320><main_process><331> ======== step 1 =========
<1078><00:05:27:320><main_process><333> ======== step 2 =========
<1078><00:05:27:320><main_process><99> SIGNAL WAIT

이렇게 accept만 타고..write시에 signal을 못받는건지..아니면 클라이언트의 이상인지..클라이언트는 종료하지 않고..멈춰있고 서버는 accept다음으로 넘어가지도 않습니다.
그러다가 클라이언트를 강제로 종료하면

<1078><00:05:20:460><main_process><99> SIGNAL WAIT
<1078><00:05:27:320><main_process><111> accept
<1078><00:05:27:320><main_process><331> ======== step 1 =========
<1078><00:05:27:320><main_process><333> ======== step 2 =========
<1078><00:05:27:320><main_process><99> SIGNAL WAIT
<1078><00:17:05:461><main_process><116> ==================== step 3 ==========
<1078><00:17:05:461><main_process><126> [02][yurina/이문선][F][0]
<1078><00:17:05:462><main_process><99> SIGNAL WAIT
<1078><00:17:05:462><main_process><116> ==================== step 3 ==========
<1078><00:17:05:462><main_process><121> disconnect
<1078><00:17:05:462><main_process><99> SIGNAL WAIT

이렇게 나머지 코딩이 실행됩니다...

왜 accept하고 블럭킹 되는걸까요...rts문제인가요?

dolsemix의 이미지

      _debug(_fl, " SIGNAL WAIT\n"); 
      rtn    = sigwaitinfo(&set, &si); 

여기서 블록되겠군요... 클라이언트에서 메시지를 입력한 후 서버 프로세스에다 시그널(제일 만만한게 SIGUSR1, 2)을 보내보시면 확인가능합니다.

kill -SIGUSR1 server_process_id

자세한 내용은 "POSIX signals"를 참조하시기 바랍니다.

담배 고만 펴야겠다...

yurina의 이미지

죄송한데요...여기서
어떠한 결과가 나와야 블록되는 건가요?
잘 모르겠어요....
해보니까...signal을 보내니까...그냥 서버랑 클라이언트랑
죽던데요...^^a

dolsemix의 이미지

우선 여기서 연산자가 좀 이상하구요...
if(rtn = SIGRTMIN)

그래도 블록될 때 커맨드라인에서 테스트용으로 시그널 날릴려면
kill -SIGRTMIN server_process_id

소스를 보니 sigwaitinfo()가 SIGRTMIN을 받지않는 이상 read를 할 수 없는 구조네요... 그렇다면 어느 누군가가 SIGRTMIN을 보내야 하는데... 감시하려는 소켓 fd를 setup_sigio()에다 등록하여 시그널을 자동으로 발생시키는 방식이군요.... 별문제는 없어보입니다만..

담배 고만 펴야겠다...

yurina의 이미지

주신말씀 정말 도움 많이 되었습니다...
정말정말 고맙습니다~~~~*^^*
좋은 하루 되시구요...
이거 보니까 아침부터 기분이 확 좋아졌습니다...
정말정말 감사합니다~~~

yurina의 이미지

음...SIGRTMIN을 보냈는데...
서버에서 인식을 못하더군요....흠...
그렇다면.......해결의 실마리를 조금 주시면 안될까요?

frowt의 이미지

'if(rtn = SIGRTMIN)'
이므로 SIGRTMIN 을 보내봤자 결과는 같습니다.
그냥 대충 유추 해보면..
'if(rtn == SIGRTMIN)'
가 되어야 할것같고, 다른 프로세스 혹은 쓰레드에서
이벤트가 발생할때마다 SIGRTMIN 을 발생시키는 구조인것 같군요.. 다시말해서 프로그램의 다른쪽에서 시그널을 발생시켜야 하는데 그게 발생이 안된다는 얘기입니다. 함 테스트 해보세요.. 다른 프로세스에서 시그널을 계속 발생시켜보세요..

client 가 죽었을때는 SIGPIPE가 발생합니다. 그래서 loop 에서 걸려서 로그가 떨어지는것으로 보이네요..

돌아가는 최소한의 소스를 올려주셔요..
이렇게 함수만 올려주시면 해결이 안되요..

dolsemix의 이미지

RTOS or RT Linux 환경에서 동작하는 프로그램인가 봅니다.
만약 본인이 사용하고 계신 리눅스가 Real Time Patch Version이 아니라면 SIGRTMIN이라는 시그널이 발생할 리가 없겠죠...
각설하고.... 단일프로세스에서 다중 소켓을 처리하는 프로그램을 만들려는 의도인듯 한데 select() 메카니즘을 이용한 자원할당방법이 더 적합해 보입니다..

담배 고만 펴야겠다...

westin의 이미지

if (SIGRTMIN == rtn) 도 좋은 습관입니다 ^^

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.