[PHP] 브라우저가 닫히면 자동으로 세션을 파기하거나 어떤 작업을 하려면...

사랑천사의 이미지

안녕하세요?

세션을 만들고 이 세션에 대한 고유번호를 따로 부여한 뒤 이것을 DB에 등록을 했습니다. 하지만, 브라우저가 닫히게 되면 세션을 파기하고 DB에 기록된 관리용 세션 자료를 날려 줘야 하는데 이걸 어덯게 해야 할지 모르겠습니다. Telnet같은 경우 접속이 끊어지면 그 상태에서 끊어지면서 동시에 세션을 제거 한다거나 DB에서 기록을 지우는 것이 쉽지만, 웹은 어떻게 해야 할 지 모르겠습니다. 아래 함수코드와 세션을 시작하는 코드등을 넣겠습니다.
-- session.php --

<?php
  require_once ($site_path."include/definitions.php");
  require_once ($site_path."include/functions.php");
  require_once ($site_path."include/config.php");
 
  session_save_path ($session_path);
  session_cache_limiter ("nocache, must-revalidate");
  session_start ();
  $자료망 = 자료망연결 ($db_hostname, $db_name, $db_username, $db_password);
  if (!is_resource ($자료망)) {
    기록 ("DB: DB접속 실패! -- ".@mysql_error ());
  } 기록 ("DB: DB접속 성공! -- User = $db_username, DB = $db_name");
 
  if (!connect_register ($자료망, "web"))
    session_destroy ();
?>

-- functions.php --
<?php
 
  function 출력파일준비 ($파일명, $출력종류) {
    if ($출력종류 != "t" && $출력종류 != "w" && $출력종류 != "h") return false;
    $fh = @fopen ($파일명, "r");
    if (!$fh) {
      return false;
    }
    while (!feof ($fh)) {
      $전체문장 .= fgetc ($fh);
    }
    @fclose ($fh);
    if ($출력종류 == "w") {
      $전체문장 = htmlspecialchars ($전체문장);
      $전체문장 = nl2br ($전체문장);
    }
    elseif ($출력종류 == "t") {
      $전체문장 = strip_tags ($전체문장);
      $전체문장 = wordwrap ($전체문장);
    }
    else return $전체문장;
    return $전체문장;
  }
 
  // 명령어 해석기 -- 미완성. 차후 나머지 작성!
  function 명령해석기 ($명령줄) {
    global $cmdlst;
    $tmp = explode (" ", $명령줄);
    if (($번호 = $cmdlst->검색 ($tmp[0])) == -1) return false;
  }
 
  // DB 접속 함수
  // 반환값
  // MySQL DB 자원이 반환되면 정상!
  // -1:인자중 하나 이상이 공란임.
  // -2:인증 실패.
  // -3:DB가 존재하지 않음.
  function 자료망연결 ($대상, $이름, $사용자, $암호) {
    if (empty ($대상) || empty ($이름) || empty ($사용자) || empty ($암호))
      return -1;
 
    if (!$자료망 = @mysql_connect ($대상, $사용자, $암호))
      return -2;
 
    if (!@mysql_select_db ($이름, $자료망))
      return -3;
 
    return ($자료망);
  }
 
  // 일지 기록 함수
  function 기록 ($내용) {
    global $log_path;
    global $main_log;
 
    $file = $log_path.$main_log;
    if (!file_exists ($file))
      if (!file_put_contents ($file, "-- 기록 시작 --\r\n")) return false;
 
    $일지 = "[".date ("Y-m-d H:i:s")."] ".$내용."\r\n";
    if (!file_put_contents ($file, $일지, FILE_APPEND))
      return false;
 
    return true;
  }
 
  function connect_register ($dbcon, $type) {
    global $db_session;
    $결과 = @mysql_query ("SELECT `sess_num` FROM `$db_session`
                                  ORDER BY `sess_num`",
                          $dbcon);
    if ($결과 === false) {
      기록 ("세션: 초기 쿼리 실패! = ".mysql_error ());
      return false;
    }
    $순번 = 0;
    while ($세션번호 = @mysql_fetch_row ($결과)) {
      if ($세션번호[0] != $순번) break;
      $순번++;
    }
    if ($type == "web") {
      $ident = "'$_SERVER[REMOTE_ADDR]', ''";
    }
    else {
      $ident = "'$_SERVER{REMOTEHOST]', '$tty'";
    }
    echo ("Debug: Ident = $ident\n");
    $now = time ();
    $query = "INSERT INTO `$db_session` VALUES ($순번, $ident, $now)";
    if (@mysql_query ($query, $dbcon))
      기록 ("세션: 세션 등록 성공! -- Sesssion_Number = $순번");
    else {
      기록 ("세션: 세션 등록 실패! -- Session_Number = $순번".
            mysql_error ());
      mysql_free_result ($결과);
      return false;
    }
    mysql_free_result ($결과);
  }
?>

뭐 쓰잘 것 없는 내용도 많이 들어간 거 같은데.. 아무튼... 어떻게 하면 브라우저가 닫힐 때 세션을 자동으로 파기하고 DB에서 기록을 지울 수가 있을 까요? 흐휴... 웹프로그래밍 쪽을 잘 모릅니다. 그래서 이렇게 해매고 있네요. Shutdown 관련 함수를 지정 해 놓는다고 하더라도, 그건 스크립트가 멎어 버리면 자연히 세션을 다 파기해 버릴 텐데 Web이 어느정도 비동기 방식이고, 재차 웹서버를 통해 자료를 주고 받으며 세션을 통해 자료가 보관되는 방식인데(물론 여긴 쿠키도 쓰이겠죠.) 세션 자체가 파기되면 안 되겠죠. 연결 검사 함수 같은걸 써야 하려나.. 그런게 있떤데 말이죠. 이게 어덯게 쓰이나는 잘 모르겠습니다만...

뭔가 좋은 방법이 없을까요... 지금 메뉴얼에서 레퍼런스 뒤지는 중입니다만, 마땅한게 별로 없군요 훗! 시간 단위로 검사를 해서 지워야 할지.. 세션을 으음...

skysign의 이미지

결론부터 말씀드리면, 브라우저가 닫힌 것을 웹서버에서 알 수 있는 방법은 없습니다.
따라서, 완벽하게 브라우저가 닫힌 것을 처리하는 것은 불가능하구요...
자바스크립트로 브라우저가 닫힐 때, 새창을 열어서
웹서버에 접속하고 그 때, 세션값을 지우는 방법이 있기는 하겠지만...
이방법도 완벽하게 동작하지는 않을 겁니다.

브라우저 클릭할 때 마다 시간 값을 갱신해서,
너무 오래동안 클릭이 없는 경우에만 지우는 방법 밖에는...

dormael의 이미지

보통은 세션 타임아웃 시간을 두고 이 시간이 경과된 세션의 데이터를 삭제하는 방법을 쓰는걸로 알고 있습니다.
그 세션으로 요청이 들어올 때마다 타임아웃을 연장해주고 cron이나 다른 프로세스에서 타임아웃된 세션을 소거해 줍니다.

php의 경우 특성상 cron을 쓰지 않는다면 매 요청마다 타임아웃된 세션을 소거해 주는 코드가 들어가야 할 수도 있습니다.
아니면 관리 페이지에서 관리자가 명시적으로 삭제해 주는 명령이 있어도 되겠네요.
만일 별도로 세션 데이터를 관리하는게 아니고 php의 함수를 쓰시는 거라면 아마 알아서 지워질 겁니다.

-- Signature --
青い空大好き。
蒼井ソラもっと好き。
파란 하늘 너무 좋아.
아오이 소라 더좋아.

송효진의 이미지

session.gc_probability = 1
session.gc_divisor     = 100

세션을 별도로 관리하더라도 php 세션함수로 등록을 하면
위의 값에 의해 확률적으로(1/100) 가비지컬렉팅 됩니다.
DB세션으로 작성하신다면, 가비지 컬렉팅과는 별도로
SELECT 구문에서 last_connect >= '-1 HOURS'::INTERVAL 처럼 제한을 주면
효과가 괜찮을듯 합니다.

emerge money

사랑천사의 이미지

잘 모르긴 몰라도. 이런건 어덜까요...
Rx보드의 경우... 접속 여부 검사 시간이란게 있던데.. 이 시간 단위가 60초 이고 (표준 설정이...) PHP스크립트가 리프레쉬 될 때 마다 이 시간이 넘었나를 검사하고 넘았다면 검사를 해서 세션이 끊어 졌따면 DB에서 삭제를 해 버리더군요. 그런 방법도 괸찮을까요? 그리고 session_destroy를 해 주지 않으면 세션 데이터파일은 세션 데이터 저장 경로에 그대로 남는것으로 알고 있습니다.(저의 경우 실험 결과도 그랬습니다.)

제가 세션을 다루려고 한 방식은 이렇습니다.
1. 세션을 시작한다.(방식은 서버=파일, 클라이언트=쿠키)
2. 고유의 세션 번호를 부여한다.(이것은 DB를 탐색해서 빈 번호를 찾는다.)
3, 고유의 세션 번호로 이것을 DB에 등록한다.(세션 고유번호, IP Address-접속자-, 세션이 등록된 시간 등)
이렇게 되면 실제 세션 자료는 파일로 기록되어 작업이 될 겁니다. 하지만 이 세션이 있음을 DB에 등록 한 경우 DB에 지속적으로 기록이 쌓이게 되겠죠. 하지만, 세션이 종료된 경우 이것을 검사해서 제거 해 주어야 합니다.(이 레코드를) 마치 유동 IP 주소를 재사용 하는 것과 같습니다. 그러니까 세션 자료는 PHP의 세션 기능으로 관리 하되, 세션이 생성 되었음을 DB에 등록하고 이것을 기반으로 서비스상의 세션을 관리 하려는 것입니다.(적은 소스를 보시면 아시겠지만)

웹프로그래밍이 익숙치 않아서 힘들군요... 특히 이 세션 처리 문제라던가 하는 부분들 말이죠 후훗. (디쟈인도 큰 문제가 되고 있습니다만.)

아무튼 말씀 해 주신 것들은 생각 해 보겠습니다. 실제로도 그런 방식으로 작동 하는 사이트들이 많은 것으로 알고 있습니다. 그런데 아무리 기다려도 로그인이 안 풀리는 그런 사이트들도 있어서요. 사용자가 로그아웃 하지 않으면 말이죠. 물론 브라우저를 닫아 버리면 세션이 지워지면서 접속도 지워 지더군요. 그런걸 구현 해야 해서 말이죠. 특히 위에 말한 Rx 보드 같이.. 흡... rgboard.com ... 아시죠? 으음.. 아무튼.. 그럼.. (물론 Rx 보드. 분석 해 보거나 할 수도 있는데, 구현을 좀 다르게 하고 싶거든요.)
----
일어나라! 싸워라! 그리고 이겨라!
다만!!! 의미 있는 것에 그 힘을!!!
그 능력과 노력을!!!

사람천사

송효진의 이미지

php 세션함수로 등록할 수 있습니다.
http://kr.php.net/manual/en/function.session-set-save-handler.php
php 는 방대한 라이브러리를 통해 웹 프로그래밍이 매우 쉬워집니다.

브라우저가 꺼지면 로그아웃 되는것은,
쿠키가 지워졌기 때문인 단순한 이유이고,
서버에서 체크를 하지는 못합니다.
브라우저가 서버에 예전 세션키를 보내지를 못해서,
서버가 로그인 했다는 응답을 못하는것일 뿐입니다.

emerge money

사랑천사의 이미지

근대 제가 말 하는 것은, 세션은 세션데로 하고... DB에 등록 한 다는 것은.. 세션이야 어차피 파일에 저장 될 거 아닌가요.. PHP의 세션이 아니라 ... 물론 관련은 있죠... 접속 정보라고 해야 겠쬬... 그걸 DB에서 갱신 해 주는 방법에 대한 겁니다. PHP의 세션이 끊어져 버리면 DB에 기록된 접속 기록도 지워야 된다.. 뭐 이런 건데. 세션 정말 어렵군요. 계념이 제대로 안 잡힌 건지... 아니, 뭔가 근본적으로 안 되는 것을 하려고 하는 건지... 몇몇 프로그램들의 경우 그게 되거든요. 접속 했다는 기록을 접속이 끊어지면 검사해서 지워 준다는 거죠. session_destroy는 어떤 이유에서인지 하지 못 하지만 말이죠. 뭐 가상 세션을 하나 더 만든다고 생각 하시면 될겁니다. 하지만 연결상의 세션을 말 하는 거지 PHP에서 처럼 자료의 세션 사용시 영구적 유지등을 위한 것은 아닙니다. 소스를 적었는데 이게 이해 하기에는 난해했거나... 별로 도움이 안 되신거 같네요 제 이야기를 이해 하시는데...

어쩔 수 없죠.. 다른 프로그램 보고 어느정도의 알고리즘이나 모델을 모방 해 보는 수 밖에요. 세션에 대한 부분도 좀 공부를 하고 말이죠. 흐흠.
----
일어나라! 싸워라! 그리고 이겨라!
다만!!! 의미 있는 것에 그 힘을!!!
그 능력과 노력을!!!

사람천사

송효진의 이미지

제 말은 php 의 세션 대신 동작하는 세션 함수를 만들어 사용하실 수 있다는 겁니다.
어차피 파일에 저장되는것이 아니고,
DB 에 저장할 수 있다는 거죠.
세션을 2개 유지할 필요가 없습니다.
위의 링크 함수가 그것입니다.

브라우저 접속을 끊으면 세션이 지워지는것이 아닙니다.
브라우저가 서버에 접속을 하면
서버는 세션키가 쿠키에 구워졌는지 검사하고,
없으면 세션키를 생성하여 쿠키로 굽습니다.
브라우저는 세션키를 쿠키로 갖고 있죠.
서버는 그 세션키를 근거로 하나의 클라이언트임을 확인합니다.
브라우저를 닫으면, 쿠키가 지워집니다.
서버에서 생성한 세션키 값을 잃어버리는 거죠.
브라우저가 다시 접속할 때 똑같은 쿠키를 직접 구워내지 않는 한,
서버는 새 접속으로 인식합니다.
예전 세션키는 지워지지 않았지만, 브라우저가 그 세션키를 가지지 않았으니까요.

아래는 php 5.x & postgresql 을 이용하는 사용자 세션 클래스 예제 입니다.
관련 라이브러리를 포함하지 않아서 동작은 안하지만,
어떤식으로 하는것인지는 금방 아실 수 있습니다.

<?php
 
define('SESS_LIFE', 7200);
 
class PostSESS
{
    public $db;
 
    function sess_open($save_path, $session_name)
    {
        global $db;
        $db = new SHJPostgreSQL(COMMONPATH.'db_acc.ini');
        $this->db = &$db;
        return true;
    }
 
    function sess_close()
    {
        $this->db->close();
        return true;
    }
 
    function sess_read($key)
    {
        $this->db->select('sessions',
            'value',
            array('sesskey = \''.$key.'\'',
                'expiry > \'now\'::TIMESTAMPTZ'),
            // 읽을때 시간제한을 둘 수 있기 때문에,
            // 굳이 세션을 삭제하지 않아도 일정시간 후 로그아웃이 됩니다.
            null,
            0, 1);
        $this->db->exec();
 
        if(false === ($ret = $this->db->field())) {
            $this->db->delete('sessions', 'sesskey = \''.$key.'\'');
            $this->db->insert('sessions',
                array('sesskey' => $key,
                    'value' => '',
                    'expiry' => CHR00.'\'now\'::TIMESTAMPTZ + \''.SESS_LIFE.' SECOND\'::INTERVAL'));
            return '';
        } else {
            return $ret;
        }
    }
 
    function sess_write($key, $val)
    {
        $this->db->update('sessions',
            array('value' => pg_escape_string($val),
                'expiry' => CHR00.'\'now\'::TIMESTAMPTZ + \''.SESS_LIFE.' SECOND\'::INTERVAL'),
            'sesskey = \''.$key.'\'');
        return true;
    }
 
    function sess_destroy($key)
    {
        $this->db->delete('sessions', 'sesskey = \''.$key.'\'');
        return true;
    }
 
    function sess_gc($maxlifetime)
    {
        $this->db->delete('sessions',
            'expiry < \'now\'::TIMESTAMPTZ - \''.$maxlifetime.' SECOND\'::INTERVAL');
        // 이것은 쓸데없이 많이 쌓이지 않도록 가끔 지워주는 것입니다.
        // 위에 적은 session.x 2 개에 의해 확률적으로 동작합니다.
        return true;
    }
 
    function __destruct()
    {
        session_write_close();
        return true;
    }
}
 
$_SESS = new PostSESS;
 
session_set_save_handler(
    array(&$_SESS, 'sess_open'),
    array(&$_SESS, 'sess_close'),
    array(&$_SESS, 'sess_read'),
    array(&$_SESS, 'sess_write'),
    array(&$_SESS, 'sess_destroy'),
    array(&$_SESS, 'sess_gc')
);
 
?>

---
php 하일라이트 기능이 이상해서 그냥 code 태그로 고쳤습니다.

emerge money

송효진의 이미지

짧은 글로 요점정리 하는것이 서툽니다.
차분히 읽어주세요.

emerge money

송효진의 이미지

kldp 의 span 태그에 display:block; 설정이 들어있는것이 아닌지요.
php 하일라이트는 span 태그가 많이 들어가는데,
현재 코드 보기에서 함수명이 줄바꿈 되어 버리네요.
------
좀 더 보니 그건 아닌것 같고,
p 태그 열고서 span 태그 닫는 등의 이상한 코드들이 보이네요.
원래 그런건지, 다른 플러그인이랑 충돌하는건지 어쨌든 좀 이상해요. :)

emerge money

사랑천사의 이미지

그렇군요. 굳이 세션을 두 개나 유지 할 필요는 없겠죠. 하지만, 이런 기록상의 문제가 되기도 하네요. 세션은 자기 자신의 세션에선 동작이 이루어 지지만, 다른 세션에서.. 음음. 예를 들겠습니다. A세션에서 B세션의 데이터를 가져오거나 A세션에서 B세션을 죽인다거나 존재 여부를 확인한다거나 하는 것은 좀 힘들다는 거죠. 이런걸 가정 해 본다면 제가 말씀 드린 접속 기록 형식의 세션과 실제 PHP세션이 필요한 이유를 어느정도 아실 겁니다.

1. A세션:사용자명 = aaaa, 등급 = 사용자
2. B세션:사용자명 = bbbb, 등급 = 사용자
3. C세션:사용자명 = sysop, 등급 = 관리자

여기서 A가 B의 접속 여부를 검색 해야 한다면.. 어떻게 될까요... B가 접속 했는지 알고 싶다면 말이죠. 그리고 C에서 A를 접속 해제 시키고 싶다면.. 우선은 DB에서 접속에 대한 부분을 지워 버리면 간단해 집니다. 음음음. 사실상 관리자라 해도 사용자의 브라우저를 원격지에서 사이트 차원의 기술로 닫아 버린다거나 하는건 어렵겠죠 당연히. 그러므로 접속 테이블에서 지워 버리면 세션은 접속을 담당하고 있긴 하지만, 저같은 경우는 손님(?)나 일반 사용자로 로그인 사람이나 모두 세션을 부여하고 잇습니다. 이렇게 되면 DB에서 접속 여부를 확인 하게 되고 끊어 지는 거죠 뭐. DB에서 접속 여부를 확인 한다면. 그리고.. 글은 쭈욱 다 정확히(?) 보고 있었습니다.

제 말은 php 의 세션 대신 동작하는 세션 함수를 만들어 사용하실 수 있다는 겁니다.
어차피 파일에 저장되는것이 아니고,
DB 에 저장할 수 있다는 거죠.
세션을 2개 유지할 필요가 없습니다.
위의 링크 함수가 그것입니다.

위에 제시해 주신 함수에 대한 내용은 메뉴얼을 읽어 보았고, 이전에 세션 함수들에 대해서 조사를 할 때 보았던 부분입니다. 그러나 제가 생각 하고 있는 것이 그런 것이 아니었고, 말씀 드린 바와 같이 어차피 접속 정보등의 시스템상 기록과 자료의 클라이언트간의 공유등을 위해서 DB에도 기록 되어야 하고 실제 사용자 개인의 세션도 필요했기 때문에 고려하지 않았습니다. 아무튼 감사드립니다.

브라우저 접속을 끊으면 세션이 지워지는것이 아닙니다.
브라우저가 서버에 접속을 하면
서버는 세션키가 쿠키에 구워졌는지 검사하고,
없으면 세션키를 생성하여 쿠키로 굽습니다.
브라우저는 세션키를 쿠키로 갖고 있죠.
서버는 그 세션키를 근거로 하나의 클라이언트임을 확인합니다.
브라우저를 닫으면, 쿠키가 지워집니다.
서버에서 생성한 세션키 값을 잃어버리는 거죠.
브라우저가 다시 접속할 때 똑같은 쿠키를 직접 구워내지 않는 한,
서버는 새 접속으로 인식합니다.
예전 세션키는 지워지지 않았지만, 브라우저가 그 세션키를 가지지 않았으니까요.

이 부분에 대해서 역시 말씀을 익히 해 주셨을 때 이해를 했었고 어느정도는 알고 있었습니다. 그래서 혹시나 하여 적은 부분이 일정 시간 간격으로 세션의 무결성을 검사하고 무결성이 검증 되지 않는 세션은 삭제해 버리고 DB에서도 접속 기록을 없에 버리는 방향에 대해서도 적은 것으로 기억 합니다 ...

아무튼 감사합니다. 많이 배웠습니다. DB세션도 쓸 가 생각 해 봤는데.. 뭐 어차피 그래도 접속 관리 테이블 때문에 가상 세션 하나와 실제 세션 하나가 되겠지만요. DB세션을 쓰기엔 현제 실험하고 작업 하는 시스템이 바쁘군요. 차후 계획에는 세션에 대한 처리 엔진을 DB용으로도 넣어 볼 생각입니다.(MySQL) 그리고 DB엔진 자체도 MySQL, SQLite... 이렇게 해 볼 생각 입니다. SQLite가 MySQL에 비해 직접 파일 접근 기반이고 해서 여러 클라이언트들이 사용 할 경우 어떤 문제가 생길지에 대한 것은 잘은 모르겠습니다만 흐흐흠.

아무튼 감사합니다.
PS:근대 C로 CGI 짜는건 좋은 방법이 아니겠죠?(원래 전 C프로그래머라서...)

추가.
quote 라고 했더니 안 먹혀서 그냥 이거 다 code로 바꾸었습니다 죄송합니다 윽.
----
일어나라! 싸워라! 그리고 이겨라!
다만!!! 의미 있는 것에 그 힘을!!!
그 능력과 노력을!!!

사람천사

ironiris의 이미지

c로 cgi를 짜는 것은 경우에 따라서 더 좋을수있습니다.

사랑천사의 이미지

                $dbqry="
                        INSERT INTO `$db_table_connect`
                                ( `con_num` , `con_mb_id` , `con_mb_icon` ,
                                        `con_date` , `con_ip` )
                        VALUES
                                ( '', '$mb[mb_id]', '$mb[mb_icon]',
                                        '$now', '$REMOTE_ADDR'
                                )
                ";
                $tmp=query($dbqry,$dbcon,1);
                if(!$tmp) {
                        $dbqry="
                                UPDATE `$db_table_connect` SET
                                        `con_mb_id` = '$mb[mb_id]',
                                        `con_mb_icon` = '$mb[mb_icon]',
                                        `con_date` = '$now'
                                WHERE con_ip = '$REMOTE_ADDR'
                        ";
                        query($dbqry,$dbcon);
                }
                $dbqry="
                        DELETE FROM `$db_table_connect`
                        WHERE `con_date`+$site[st_connect_time] < '$now'
                ";
                query($dbqry,$dbcon);
        }

근대 문제는 저 코드를 보니.. DELETE 쿼리를 날린 대가 있는데. 저 부분이 가장 이해가 힘들군요. st_connect_time는... 사이트의 접속 검사 시간입니다.(접속 여부) 즉 이 값이 60이라면.. 연결 시간 + 값 = x 햇을 때 x가 현재 시간보다 작으면 그 접속현황 레코드를 지운다 이거거든요 흠. 머리가 안 돌아 가네요. 저거랑. 접속 끊기면 지운는 거랑 뭔 상관이죠 훗. 물론 저 부분이 매번 갱신이 됩니다. 아니 실행이 됩니다. 사이트가 불러 질 때 마다. 어떻게 하면 좋을까를 생각 하다가... 저 코드를 어떻게 응용 할 수 없을까.. 생각을 해 보고 넣어 봤습니다. 저걸 보니 저걸 어덯게 응용은 못 하더라도 아이디어는 떠오르긴 하는 군요 음.
----
일어나라! 싸워라! 그리고 이겨라!
다만!!! 의미 있는 것에 그 힘을!!!
그 능력과 노력을!!!

사람천사

사랑천사의 이미지

충분히 이해 했습니다. 한가지 실험을 해 봤죠. RG-Board가 설치된 서버 하나를 가지고 장난을 좀 쳐 봤습니다. 하나의 방법이군요 저것도. 어찌 되었던 일정 기간마다 검사를 해서 DB에서 지우는 것이 가장 중요한 포인트군요.
----
일어나라! 싸워라! 그리고 이겨라!
다만!!! 의미 있는 것에 그 힘을!!!
그 능력과 노력을!!!

사람천사

사랑천사의 이미지

대강 완성 했습니다. 아래 소스 봐 주세요. 문제점이나 치명적인 버그가 있다면.. 지적 해 주시면 더 좋고요... 제대로 웹프로그램을 작성 하기 시작 해고 세션 부분에서의 첫번째 성공이군요(그게 그렇게 행복하냐 해죽거리게?)
-- session.php --

<?php
  require_once ($site_path."include/definitions.php");
  require_once ($site_path."include/functions.php");
  require_once ($site_path."include/config.php");
 
  session_save_path ($session_path);
  session_cache_limiter ("nocache, must-revalidate");
  session_start ();
  $자료망 = 자료망연결 ($db_hostname, $db_name, $db_username, $db_password);
  if (!is_resource ($자료망)) {
    기록 ("Main: DB접속 실패! - Errno: $자료망");
  }
  기록 ("Main: DB접속 성공! - User = $db_username, DB = $db_name");
 
  $설정 = get_configs ($자료망);
  if (!$설정) {
    기록 ("Main: 환경설정 읽기에 실패함!");
    session_destroy ();
  }
 
  $now = time ();
  if (!isset ($_SESSION["sess_num"])) {
    if (!$sess_num = connect_register ($자료망, "web")) {
      session_destroy ();
      exit;
    }
    else {
      session_register ("sess_num");
    }
  }
  else {
    $질의 = "SELECT count(*) AS exist FROM `$db_session_table` WHERE
             `sess_num` = ".$_SESSION["sess_num"];
    $결과 = @mysql_query ($질의, $자료망);
    if (!$결과) {
      기록 ("Main: DB오류 - ".mysql_error ());
      session_destroy ();
      exit;
    }
    $자료 = mysql_fetch_row ($결과);
    if ($자료[0] == 0) {
      $_SESSION["sess_num"] = connect_register ($자료망, "web");
      if (!$_SESSION["sess_num"]) {
        기록 ("Main: 세션 교체 실패!");
        session_destroy ();
        exit;
      }
    }
    else {
      @mysql_free_result ($결과);
      $질의 = "UPDATE `$db_session_table` SET `st_time` = ".$now.
              " WHERE `sess_num` = ".$_SESSION["sess_num"];
      $결과 = @mysql_query ($질의, $자료망);
      if (!$결과 || mysql_affected_rows ($자료망) == 0) {
        기록 ("Main: 세션 정보 갱신 실패!");
        session_destroy ();
        exit;
      }
      @mysql_free_result ($결과);
    }
  }
  $질의 = "DELETE FROM `$db_session_table` WHERE
           `st_time`+".$설정["con_check_time"]." < $now";
  @mysql_query ($질의, $자료망);
?>

-- Function:connect_register () --
  // 접속 기록 등록
  function connect_register ($dbcon, $type) {
    global $db_session_table;
    $결과 = @mysql_query ("SELECT `sess_num` FROM `$db_session_table`
                                  ORDER BY `sess_num`",
                          $dbcon);
    if ($결과 === false) {
      기록 ("Session: 초기 질의 실패! = ".mysql_error ());
      return false;
    }
    $순번 = 1;
    while ($세션번호 = @mysql_fetch_row ($결과)) {
      if ($세션번호[0] != $순번) break;
      $순번++;
    }
    if ($type == "web") {
      $ident = "'$_SERVER[REMOTE_ADDR]', ''";
    }
    else {
      $ident = "'$_SERVER{REMOTEHOST]', '$tty'";
    }
    $now = time ();
    $query = "INSERT INTO `$db_session_table` VALUES ($순번, $ident, $now)";
    if (@mysql_query ($query, $dbcon))
      기록 ("Session: 세션 등록 성공! -- Sesssion_Number = $순번");
    else {
      기록 ("Session: 세션 등록 실패! -- Session_Number = $순번".
            mysql_error ());
      mysql_free_result ($결과);
      return false;
    }
    mysql_free_result ($결과);
    return ($순번);
  }

----
일어나라! 싸워라! 그리고 이겨라!
다만!!! 의미 있는 것에 그 힘을!!!
그 능력과 노력을!!!

사람천사

댓글 달기

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