서버에서 클라이언트로 메세지를 보내기 전에 먼저
접속이 현재 제대로 이루어져 있는지 확인해 보아야 한다.


/**
   * 메세지를 모든 다른 클라이언트에게 보낸다.
   */

private void broadcast(Client fom, String message) {
    // 연결이 끊겨진 클라이언트들을 잠시 저장하기 위해 사용
    Vector zombies = new Vector(5);

    Enumeration enum = clients.elements();
    while ( enum.hasMoreElements() ) {
        // 클라이언트 객체가 발송자인 경우 무시
        if (client == from) {
            continue;
        }

        if (client.socket == null) {
            zombies.addElement(client);
            continue;
        }
       client.sendMessage(message);
    }

    enum = zombies.elements();
    while ( enum.hasMoreElements() ) {
        Client client  = (Client) enum.nextElement();
        clients.removeElement(client);
    }
}


메세지를 보낼때 문제가 생기면 try catch 부문에서 잡을 수도 있을것 같다.
하지만 어느게 성능이 더 좋은지 잘 모르겠다.

현재 있는 것은 다음과 같이 움직인다.
1. 살아 있나?
2. 살아 있으면 메세지 보냄
3. 죽어 있으면 Enumeration 에 저장
4. 메세지 전부 보낸후 각 Client 삭제 처리

하지만 메세지를 보낼때 문제가 생긴다면 다음과 같을것이다.
1. 메세지 보냄
2. 죽어 있으면
3. 죽어 있는 클라이언트 삭제
4. 살아 있으면 메세지 보냄.

첫번째것은 각 메세지를 보낼때마다 Enumeration 를 생성하는 로드.
두번째것은 죽은 클라이언트들에게 보내는 메세지 로드와 예외 처리 부분의 로드.


아직은 실력이 없어서 확인을 못 해 본다.
채팅 서버의 경우 처럼 쓰레드별로 클아이언트의 소켓 연결을 전담해서 처리하면
프로그램은 아주 간단해 진다. 하지만 쓰레드를 생성하는 것이 프로세스의 생성보다는
훨씬 가벼운 일이지만, 많은 클라이언트의 동시 접속을 처리하기 위해 네트웍 연결마다
쓰레드를 생성하게 되면 메모리 등 리소스 오버헤드가 커지게 된다. 이런 경우에는
쓰레드 하나에 몇 개의 네트웍 연결을 할당하는 방식으로 개선할 수 있다.

쓰레드 하나가 여러 개의 네트웍 연결을 처리하려면 이 채팅 서버처럼 readLine()과 같은
블로킹 메소드를 사용하면 메시지가 들어올 때까지 이 메소드에서 블록되어 버리기 때문에
그동안 다른 네트웍 연결을 처리할 수가 없다. 따라서 이런 경우에는 넌블로킹 메소드인
InputStream의 available() 메소드나 Reader의 ready()를 사용하여 입력이 있는지 여부를
조사해보고, 입력이 있을 경우 현재 가능한 만큼만 읽어들이는 메소드인 read(byte[]) 혹은
read(char[]) 메소드를 사용해야 한다.

단일 쓰레드로 위의 채팅 서버를 고친다면 단일 쓰레드 부분은 다음과 같은 코드로 실행
될 수 있따. 책의 부록에 포함됨 NonBlockingChatServer.java 소스 코드를 참고하기 바란다.


/**
   * 각 클라이언트의 소켓 입력 상태를 검사한다.
   */

public void run() {
    wile (true) {
        Enumeration enum = clients.elements();
        while ( enum.hasMoreElements() ) {
            Client client = (Client) enum.nextElement();
            try {
                if ( client.in.ready() ) {
                    client.getMessage();
                }
            } catch (IOException e) {
                System.err.println(client.getname()+ " 출력 에러 : " + e.getMessage() ) ;
                client.closeSocket();
            }
        }
        try {
            Thread.sleep(10); // 잠깐씩 쉰다.
        } catch ( InterrupteExecption e) { }
    }
}


서버에서 유령사용자 처리는 클라이언트의 일방적인 PING (Not ICMP but send dummy byte)을 사용하도록 함.
irc를 이용해서 서버를 만들고,
클라이언트는 java applet 과 javascript로 만들어 낸다.

irc에 대한 자료는 나중에 추가하도록 한다.

세이클럽, cafe24 등이 irc 기반 이라고 함
페이지 이동
pageList (target, start, scale, view, total, URL)
target = 표시할 객체
start = 글위치 (페이지 단위가 아니고 순차적인 글의 위치)
scale = 페이지의 글리스트 갯수
view = 표시될 페이지 갯수
total = 전체 글 갯수
URL = 링크URL (마지막에 '&'은 빼고... 안빼도 상관없지만^^)


<TABLE bgColor=#999999 height=30><TR><TD><DIV id=pageListDIV></DIV></TD></TR></TABLE>
<SCRIPT>
  function pageList (target, start, scale, view, total, URL) {
    var html = "";
    var reLoading = " <a href=\"javascript:pageList(" +target.id+ ",{page}," +scale+ "," +view+ "," +total+ ",'" +URL+ "');\">{PAGE}</a>";

    if (total % scale) add = 1; else add = 0;
    maxPage = Math.floor(total / scale) + add;

    begin = Math.floor(Math.floor(start/(scale * view)) * view + 1);
    end = Math.floor(begin + view - 1);
    if(end > maxPage) end = maxPage;

    if (begin > 1) {
      html += " <a href='" +URL+ "&start=0'>[1]</a>";
      html += reLoading.replace ("{page}", (begin-2)*scale).replace ("{PAGE}", "◀:");
    }
    for(var i=begin; i<=end; i++) {
      page = (i - 1) * scale;
      if(start != page) {
        html += " <a href='" +URL+ "&start=" +page+ "'>[" +i+ "]</a>";
      } else {
        html += " <b>" +i+ "</b>";
      }
    }
    if (end < maxPage) {
      if (end < maxPage-1) {
        html += reLoading.replace ("{page}", end*scale).replace ("{PAGE}", ":▶");
      }
      page = maxPage * scale;
      html += " <a href='" +URL+ "&start=" +page+ "'>[" +maxPage+ "]</a>";
    }

    target.innerHTML = html;
  }
  pageList (self.pageListDIV, 0, 30, 10, 2000, 'http://phpschool.com/bbs2/inc_board.html?mode=&field=&period=&s_que=&code=tnt2&operator=&category_id=');
</SCRIPT>
<style>
img { margin:0; border-width:0; }
</style>
<table style="table-layout:fixed; overflow:hidden;">
<tr>
<td width="50px">글글글</td>
<td width="22px" height="22px" onmouseover="over.style.visibility='visible';" onmouseout="over.style.visibility='hidden'; push.style.visibility='hidden';" onmousedown="push.style.visibility='visible';" onmouseup="over.style.visibility='visible'; push.style.visibility='hidden';"
><nobr
><img name="normal" src="http://my.netian.com/~crosser/images/button_go_normal.png"
><img name="over" src="http://my.netian.com/~crosser/images/button_go_over.png" style="position:relative; left:-22; visibility:hidden;"
><img name="push" src="http://my.netian.com/~crosser/images/button_go_push.png" style="position:relative; left:-44; visibility:hidden;"
></nobr></td>
<td width="50px">글글글</td>
</tr>
</table>
역시 플래쉬는 노가다다 ;;;
( 자기가 못한다는 이야기는 안한다 ;;; )


그냥 끄적여 본건데 ...
때려치아야 겠다. ;;;


디자인은 감이다. ;;;;

난 사람이라서 못하는 것 뿐이다. ;;;;


그래도 한건 아쉬워서 올려 놓음 ;;;



"꼭 가고 싶습니다" 라고 하지 않아도 "꼭 보내 준다"

'재미' 카테고리의 다른 글

온라인에서의 말 실수  (0) 2003.07.16
[추천] 매트릭스 핑퐁  (0) 2003.07.15
박카스 CF의 문제점.  (0) 2003.07.12
[펌] 문자삐삐 메신저 아르바이트에서 생긴일  (0) 2003.07.09
가공할 협박  (0) 2003.07.09
일본인이 보는 한국  (0) 2003.07.06

+ Recent posts