사용자 삽입 이미지

GChat 을 오픈하면 개인들이 무료로 쓸수 있게 만든 리플레쉬를 통한 1:1 상담 채팅.
서버에 부하 많고 찰칵 거리는 소리때문에 개인홈페이지에 취미로나 가능함.
 
아래는 배포시 남긴 글
-----------------------------------------------------------------------------------
이번에 오픈한 1:1 전용 상담 채팅방인 GChat(http://gchat.kilho.net) 을 통해 많은 분들이 관심을 가져주셨습니다. 그중에 개인 홈페이지에 설치할려는 분들이 계셔서 간단하게 만들었습니다.
 
GChat 과는 다르게 리플레쉬 방식을 사용되었습니다.
 
원리는 하나의 관리자 페이지(server.php)가 손님의 접속을 체크하게 됩니다. 그리고 손님이 메세지를 날리면 해당 메세지가 파일에 저장되고 그것을 통해 관리자와 서로 대화를 하게 됩니다. 참고로, DB 를 사용하지 않았습니다. 해당 파일들을 설치한 폴더 뒤에 data 라는 폴더를 생성해주시길 바랍니다. 권한은 707 으로 주시면 됩니다.
원래 제가 디자인은 꽝이라 기본 틀만 해놨습니다. 자신의 개성을 살려 디자인을 입히셔서 사용하시면 됩니다.
참고로, 제로보드인 경우에는 $member[user_id] 변수를 이용하여 client.php 의 15 번째줄 $nick='손님';
를 if($member[user_id])$nick=$member[user_id];else $nick='손님';
으로 바꾸어 주시면 로긴중인 닉으로 손님 대신에 사용할수 있습니다.
 
소스들이 100라인 안팍으로 이해하기 쉽게 되어있습니다.
사용방법은 1:1 상담 링크는 client.php 로 연결합니다.
그후, 관리자분은 server.php 를 실행해 두시면 됩니다.
 
PS_1. 본 프로그램은 리플레쉬 방식이기 때문에 서버에 부하를 주게 됩니다.
그래서 많은 방문자를 가진 홈페이지에서는 절때 비추합니다.
PS_2. 부하때문에 샘플예제를 보여드리지 못해 죄송합니다. 하지만 쉽게
깔아서 테스트 해보실수 있고, 사용중인 예를 캡쳐해서 올립니다.
PS_3. 해당 소스에 대한 질문은 받지 않습니다.

Posted by 알 수 없는 사용자
,

구구단 :

http://oxtag.com/php/p/99dan.php



기념일 계산 날짜 계산 및 음력, 양력
http://oxtag.com/php/p/Date/Date.php



디데이(D-DAY) 카운터 사용법 :
http://oxtag.com/php/p/Date/D-DAY/user.php



기념일 카운터 사용법 :
http://oxtag.com/php/p/Date/D-DAY/user2.php



기념일 계산,날자 계산,날짜 계산,음력 변환,양력 변환,
음양력 변환,윤달,요일 계산,남은 날짜,요일계산,며칠째,몇일째
http://oxtag.com/php/p/calendar2.php



타임스템프(Timestamp) 계산기
http://oxtag.com/php/p/timestamp_change.php
Timestamp - Date Manager
타임스템프(Timestamp) 계산기



도량형 환산표, 단위 환산, 면적 구하는 공식, 면적단위
http://oxtag.com/php/p/DoRyangHyung/
도량형 환산표, 단위 환산, 면적 구하는 공식, 면적단위



세금계산서 : 부가세포함, 부가세별도, 부가세 미포함 계산기
http://oxtag.com/php/p/tax_bill.php
세금계산서 : 부가세포함, 부가세별도, 부가세 미포함 계산기



단기,서기,육십갑자,띠 조회
http://oxtag.com/php/p/yuksipgapja.php
단기,서기,육십갑자(六十甲子),육십간지(六十干支),
십간십이지 (十干十二支),십이지신,십이간지,십이지,십이지신,십간,띠,十二辰



로또(LOTTO) 추첨기 대박나세요.
http://oxtag.com/php/p/lotto/lotto2.php



태그연습장, 웹소스보기
태그연습장 및 웹소스보기 입니다.
http://oxtag.com/html/ex/CTediter/CTediter.html



온라인 타자연습기, 웹타자연습, 타이핑연습,
웹 타자연습, 영타연습, 영문타자, 한타, 영타
온라인 타자 연습기 입니다.
온라인 타자 연습, 웹 타자연습기, 타이핑, 영타연습, 영문타자, 한타, 영타
http://oxtag.com/php/taja/taja.html




택배조회 배송조회 배송추적 배송검색 택배추적
택배조회,추적,택배검색,배송조회:호남택배,KBG택배,KGB특급,CJGLS,로젠,한진,우체국,삼성HTH,대한통운,옐로우캡,트라넷택배,현대택배,훼미리택배,고려택배,이클라인(ECLINE),아주,KT로지스,양양택배,일양택배,DHL,Fedex,UPS,EMS,경동택배,하나로택배,하나로로지스,천일화물택배
http://oxtag.com/html/ex/DoorToDoor/




경동택배 전국 영업소 전화번호 및 택배조회, 배송조회, 배송추적
경동택배 전국 영업소 전화번호 및 택배조회, 배송조회, 배송추적
http://oxtag.com/php/kdexp/



webime, web ime, web hangul ime, korea ime, webime, web_ime
외국 나갔을때 한글 윈도우 또는 한글 IME 설치가 되어 있지 않는 경우 영문을 한글로 바꿔주는 웹 IME입니다.
http://oxtag.com/php/webIme/



한자사전
http://211.46.71.249/handic/



아이콘 사이트
http://www.garamart.com/icons06071/Icon_main/iconindex.asp
http://www.garamart.com/



귀여운 퍼스나콘 모음
http://blog.naver.com/dnelfksp/40030886279



Escape ↔ Unescape
UTF8 Encode ↔ UTF8 Dncode
URL Encode ↔ URL Dncode

소스 및 미리보기 : http://oxtag.com/php/p/utf8_encode.php


URL Encode / URL Decode / Escape / Unescape ...
미리보기 : http://oxtag.com/php/p/unicode/StringConversion.php



인코딩 - 암호화,복호화
http://oxtag.com/php/p/encoder.php



파일명 한글일때 인코딩
파일명이 한글인 경우 이미지가 엑박으로 뜨거나 음악이 재생 안될때 사용하세요.
http://oxtag.com/php/p/URLChange2.php



바이오리듬 - biorhythm
http://oxtag.com/php/biorhythm2/biorhythm.php



소스 하일라이터 - 소스색상입히기
http://oxtag.com/php/SourceHighlight/



CPP2HTM - 소스하일라이트, 소스색상입히기
http://oxtag.com/php/p/CPP2HTM/input.php



후이즈 도메인 검색
http://oxtag.com/cgi/WHOIS/whois.cgi



웹 FTP, 웹FTP, web ftp
계정정보는 저장되지 않으니까 안심하셔도됨니다.
FTP 프로그램을 설치하지 않고, 계정에 접속할 수 있습니다.
http://oxtag.com/html/webftp/ftp.html
http://oxtag.com/php/webFtp/



기대 수명 계산기
http://oxtag.com/html/ex/health.html



모질라, 파이어폭스, FF 를 위한 웹표준화 가이드, 레퍼런스
http://www.mozilla.or.kr/docs/web-developer/standard/
http://developer.mozilla.org/en/docs/Gecko_DOM_Reference



PHP 메뉴얼 chm 한글 버전
http://kr2.php.net/get/php_manual_kr.chm/from/a/mirror



PHP로 만들어진 오픈형 채팅솔루션
http://phpopenchat.org/



실시간 메모 보내기, 실시간 쪽지 보내기
테스트 주소 :
                   팝   업 - http://oxtag.com/php/reChat/
                   레이어 - http://oxtag.com/php/reChat/index2.php
메모는 읽음과 동시에 자동 삭제처리 했습니다.
태그 : 접속자 아이피, 실시간 메모, 실시간 쪽지 보내기



브라우저 지원 글자 알아보기
http://oxtag.com/html/ex/len20070518.html



스누피 Snoopy HTTP 에뮬레이션, 소켓 연결
http://sourceforge.net/projects/snoopy



스크롤바, 투명스크롤바
http://oxtag.com/html/ex/scrollbar_color.html



색상표, 색상, 컬러, color
http://oxtag.com/html/rgbcolor.htm
http://oxtag.com/html/ex/colorcode/colorcode01.html



폰트 사이트
http://www.zellibbi.com/


Posted by 알 수 없는 사용자
,
웹상에서 채팅 프로그램을 구현할 때 가장 힘든 부분이 바로

HTTP 프로토콜이 접속이 바로 끊기고 상태를 저장하지 않는 접속을 이용한다는 점입니다.



즉, 소켓 프로그래밍에서 접속을 열고 닫고 하는것이 굉장히 운영체제 차원에서는 비싼 작업인 반면

이미 열려진 소켓에서 몇바이트 쯤 더 쓰는 것은 속도나 성능 면에서 전혀 문제가 되지 않는다는 것이죠

(요즘은 인터넷이 빨라서 초당 몇MB씩도 쓰고 하잖아요. 하지만 접속을 여는 데에는 여전히 시간이 걸리죠.)

 

그러나 Flash Action Script에서 지원하는 Socket 클래스를 이용하면 자신이 다운로드된 서버와

접속이 유지된 통신을할 수 있습니다.

 

본 프로그램에서는 이점을 이용하여 클라이언트로는 Flash와 자바스크립트를 이용하고

서버로는 C++로 자체 제작한 서버 프로그램을 이용하여 채팅방을 구현하였습니다.

 

본 예제는 Flash Player 9.0을 필요로 하며 Internet Explorer와 Firefox에서 동작합니다.

 

먼저 demo 페이지를 보시겠습니다.

http://astronote.org/

마우스 드래그를 통한 창이동, 창 최소화, 창 숨기기 기능을 지원합니다.


서버 프로그램

서버 프로그램은 리눅스상에서 c++을 이용하여 개발하였으며 g++을 이용하여 컴파일 하였습니다.

저는 astronote.org 서버를 집에서 dyndns와 인터넷 공유기의 port mapping을 이용하여 돌리고 있습니다.

그렇기 때문에 집에서 원하는 포트에 서버를 실행시킬 수 있지만

웹호스팅 받으시는 분들은 서버상에서 프로그램을 실행시킬 수 없다면 본 예제를 적용할 수 없습니다. 참고하세요.

 

일단 서버 소스코드를 올려드리겠습니다.



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

using namespace std;

// 접속된 클라이언트 IP를 저장하기 위한 전역 변수
struct client
{
 string ip;
 int fd;
};

class Error {}; // 에러 처리를 위한 Dummy 객체

vector<client> clients;

void *thread_comm(void *);
int load_address();

int main(int argc, char **argv)
{
    if (argc != 2)
    {
        printf("Usage : ./server [port]\n");
        exit(0);
    }

    // socket -> bind -> listen 순서로
    // 듣기 소켓 생성
    int server_sockfd;
    if ((server_sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("socket error");
        exit(0);
    }

    int val = 1;   
    if (setsockopt(server_sockfd, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof val) < 0)
 {
  perror("setsockopt");
  close(server_sockfd);
  exit(0);
    }

 struct sockaddr_in serveraddr;
 bzero(&serveraddr, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
    serveraddr.sin_port = htons(atoi(argv[1]));
    if (bind(server_sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) == -1)
    {
        perror("bind error");
        exit(0);       
    }

 printf("접속을 기다리고 있습니다.\n");
 if (listen(server_sockfd, 5) == -1)
    {
        perror("bind error");
        exit(0);   
    }

    while(1)
    {
        // 만약 듣기 소켓에 연결이 들어온다면
        // 새로운 쓰레드를 생성시킨다.
        // 새로운 쓰레드 생성시 클라이언트 소켓을 쓰레드
        // 인자로 넘겨서 쓰레드와 클라이언트가 통신하도록 한다. 
    struct sockaddr_in clientaddr;
  int client_len;
  int client_sockfd;

  try
  {
  client_sockfd = accept(server_sockfd, (struct sockaddr*)&clientaddr, (socklen_t*)&client_len);
  client cl;
  cl.ip = inet_ntoa(clientaddr.sin_addr);
  cl.fd = client_sockfd;
  clients.push_back(cl);

  pthread_t p_thread;
  if (pthread_create(&p_thread, NULL, thread_comm, (void *)client_sockfd) == -1)
  {
    perror("쓰레드 생성 실패\n");
    exit(0);
  }
  }
  catch (Error&) {}
    }
 shutdown(server_sockfd, 2);
    close(server_sockfd);
}

// 쓰레드 생성시 넘어온 클라이언트 소켓을 이용해서 클라이언트와 통신한다.
void *thread_comm(void* data)
{
    int sockfd = (int)data;
 string ip;
 for(vector<client>::iterator ci = clients.begin(); ci != clients.end(); ci++)
  if(ci->fd == sockfd)
  ip = ci->ip;

 printf("%s 에서 접속..\n", ip.c_str());
 printf("현재 접속자수 : %d 명\n", clients.size());

 char buf[1024];

 // 모든 사용자에게 접속을 알림
 sprintf(buf, "%s|connected|%d\n", ip.c_str(), clients.size());
 for(vector<client>::iterator ci = clients.begin(); ci != clients.end(); ci++)
 {
  if(write(ci->fd, buf, strlen(buf)+1) == -1)
  printf("%s 에서 쓰기 에러\n", ip.c_str());
 }

 char c;
 string line;
 try
 {
  while(read(sockfd, &c, 1) > 0)
  {
  line += c;
  if (c == '\n')
  {
    line = ip + "|" + line;
    for(vector<client>::iterator ci = clients.begin(); ci != clients.end(); ci++)
    {
    if(write(ci->fd, line.c_str(), line.length()+1) == -1)
    {
      printf("%s 에서 쓰기 에러\n", ip.c_str());
      break;
    }
    }
    line.clear();
  }
  }
 }
 catch (Error&) {}

 shutdown(sockfd, 2);
 close(sockfd);
 printf("%s 에서 접속 종료\n", ip.c_str());
 
 // 벡터에서 삭제한다.
 for(vector<client>::iterator ci = clients.begin(); ci != clients.end(); ci++)
  if(ci->fd == sockfd)
  {
  clients.erase(ci,ci+1);
  break;
  }

 try
 {
  // 자기 자신을 제외한 모든 사용자에게 끊김을 알림
  sprintf(buf, "%s|disconnected|%d\n", ip.c_str(), clients.size());
  for(vector<client>::iterator ci = clients.begin(); ci != clients.end(); ci++)
  {
  if(write(ci->fd, buf, strlen(buf)+1) == -1)
    printf("%s 에서 쓰기 에러\n", ip.c_str());
  }
 }
 catch (Error&) {}

 printf("현재 접속자수 : %d 명\n", clients.size());

 return (void *)NULL;
}


서버프로그램은 보시다시피 간단합니다.

클라이언트측에서 보내주는대로 자신을 포함한 모든 클라이언트에서 broadcasting 해 주는 것 밖에는 특별한 기능이 없습니다.

소스코드를 업로드하시고 컴파일합니다.

$ g++ -o chat-server -lpthread server.cpp


그런 다음 chat-server에 실행옵션 주고 실행합니다. 파라미터로 포트번호를 넘깁니다.

$ chmod 700 chat-server
$ ./chat-server 25000 &


그럼 OK 입니다.



클라이언트 프로그램

클라이언트 프로그램은 flash 부분과 javascript 부분으로 나누어집니다.

먼저 flash를 띄우고 첫번째 프레임에서 F9를 눌러 ActionScript 창을 띄운 후 다음과 같이 입력합니다.

 

import flash.external.ExternalInterface;
import flash.net.Socket;

var str:String = '';
var socket:Socket = null;
socket = new Socket();
socket.connect('astronote.org',25000); // 이부분은 서버 설정에 맞게 수정하세요.
socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);

function sendIt(str:String) : void
{
 socket.writeMultiByte(str+'\n', "euc-kr");
 socket.flush();
}

function socketDataHandler(event:ProgressEvent):void
{
 var str = socket.readMultiByte(socket.bytesAvailable, "euc-kr");
 ExternalInterface.call("received", str);
}

ExternalInterface.addCallback("sendIt", sendIt);


내용은 실행될 때 소켓을 열고 자바스크립트 함수에서 호출할 수 있는 sendIt 이라는 메소드를 노출했습니다.

서버로부터 자료를 받으면 received 라는 자바스크립트 함수를 호출해 줍니다.

자신의 서버 설정에 맞게 도메인명과 포트번호를 수정합니다.

저는 웹서버 설정을 euc-kr로 했기 때문에 euc-kr로 했지만 utf-8로 할 수 도 있습니다.

이제 Shift+F12를 눌러 컴파일합니다.

 

이제 자바스크립트 부분입니다.

먼저 항상 떠 있는 안보이는 frame을 만들어서 chat.htm을 띄워놓습니다. 여기에 flash로 만든 swf 파일을 올립니다.

<frameset rows='*,0' border=0 frameborder=0>
<frame name=main src=/home.htm border=0>
<frame name=sock src=/chat.htm border=0>
</frameset>

 

다음은 chat.htm의 코드입니다.

 

<script src="AC_RunActiveContent.js"></script>
<script>
if (AC_FL_RunContent == 0)
{
 alert("This page requires AC_RunActiveContent.js.");
}
else
{
 AC_FL_RunContent('codebase', 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0',
 'width', '100',
 'height', '100',
 'src', 'astrowar',
 'quality', 'high',
 'pluginspage', 'http://www.macromedia.com/go/getflashplayer',
 'align', 'middle',
 'play', 'true',
 'loop', 'true',
 'scale', 'showall',
 'wmode', 'window',
 'devicefont', 'false',
 'id', 'astrowar',
 'bgcolor', '#000000',
 'name', 'astrowar',
 'menu', 'true', 'allowFullScreen', 'false', 'allowScriptAccess','always', 'movie', 'astrowar', 'salign', '');
}

var saved = '';
var idpool = [];
var chatnum = 0;
function findid(ip)
{
 for(var i = 0; i < idpool.length; i++)
 {
  if(idpool[i].ip == ip) return idpool[i].name+"<small>("+idpool[i].id+")</small>";
 }
 return ip;
}

function update_chatnum()
{
 if(parent.main)
 {
  var cn = parent.main.document.getElementById('chatnum');
  if(cn) cn.innerHTML = '현재 접속자수 '+chatnum+'명';
 }
}

function received(s)
{
 var arr = s.split('|');
 var str = '';
 switch(arr[1])
 {
 case 'connected':
  str = arr[0] + " 접속<br>";
  chatnum = arr[2];
  update_chatnum();
  break;
 case 'login':
  str = arr[3]+"("+arr[2] + ") 로그인<br>";
  if(findid(arr[0]) == arr[0] && arr[2] && arr[3]) idpool[idpool.length] = {ip:arr[0],id:arr[2],name:arr[3]};
  break;
 case 'logout':
  str = arr[3]+"("+arr[2] + ") 로그아웃<br>";
  //if(findid(arr[0]) != arr[0] && arr[2] && arr[3]) idpool[idpool.length] = {ip:arr[0],id:arr[2],name:arr[3]};
  break;
 case 'disconnected':
  str = findid(arr[0]) + " 접속 종료<br>";
  chatnum = arr[2];
  update_chatnum();
  break;
 case 'chat':
  var name = arr[3] + "<small>("+arr[2]+")</small>";
  if(arr[3]=='') name = arr[0];
  str = "<font color="+arr[5]+">"+name + " : " + arr[4] + "</font><br>";
  if(findid(arr[0]) == arr[0] && arr[2] && arr[3]) idpool[idpool.length] = {ip:arr[0],id:arr[2],name:arr[3]};
  break;
 }
 if(str)
 {
  saved += str;
  if(parent.main)
  if(parent.main.cv)
  {
  var p = parent.main.document.createElement('div');
  p.innerHTML = str;
  parent.main.cv.appendChild(p);
  window.setTimeout('parent.main.cv.scrollTop = parent.main.cv.scrollHeight',100);
  }
 }
}

var hide = false;
var chat_closed = false;
var alpha = 100;
function onalpha(f)
{
 alpha = f.options[f.selectedIndex].value;
 if(parent.main.cr)
 {
  parent.main.cr.style.opacity = alpha/100;
  parent.main.cr.style.MozOpacity = alpha/100;
  parent.main.cr.style.KhtmlOpacity = alpha/100;
  parent.main.cr.style.filter = "alpha(opacity=" + alpha + ")";
 }
}

var col = '#000000';
function oncolor(f)
{
 col = f.options[f.selectedIndex].value;
}

function getMovieName(movieName)
{
 if (navigator.appName.indexOf("Microsoft") != -1) return window[movieName];
 else return document[movieName];
}

var chatx = 0;
var chaty = 270;

var sock;
window.onload = function(){
sock = getMovieName("astrowar");
}
</script>


AC_RunActiveContent.js 파일은 Flash에서 publish 할 때 생성된 것을 변경 없이 그대로 사용하시면 됩니다.

저는 swf 파일의 이름을 astrowar.swf 로 했습니다. 하지만 다른 이름으로 해도 무방합니다.

 

onalpha 함수와 oncolor 함수는 채팅방에서 투명도나 대화색상을 조절하기 위해 사용합니다.

 

이제 본 페이지 들어갑니다.

홈페이지의 모든 페이지에서 load 되는 head.php 등에 아래 코드를 추가하세요.

 

<!-- ---------------------------------------------------------------------- -->
<!-- ------------ 천문노트 채팅방 2007-11-24 오후 11:48 이형철 ------------ -->
<script>
var mem_id = '<?=$mem_id?>';
var mem_name = '<?=$mem_name?>'; // 이 부분만 자신의 설정에 맞게 수정하면 됩니다.
</script>

<div id=chatroom style='z-index:100;position:absolute;top:270px;right:30px;width:200px;display:none;'>
<div id=titlebar style='padding:3px;background:#F6F6F6;width:100%;'>
<span id=chatnum style="width:130;"> </span>
<a href=javascript:chat_hide() style=text-decoration:none;>[ _ ]</a> <a href=javascript:chat_close() style=text-decoration:none;>[ X ]</a>
</div>

<div id=chatroominner>
<div id=chatview style="display:block;padding:5px;width:100%;height:170;"> </div>
<input name=chatcontent id=chatcontent maxlength=95 style=width:100% style='border:0;background:whitesmoke;' onkeydown='if(event.keyCode==13)chat(this)' value='메세지를 입력하세요.' onblur="if(!this.value) value='메세지를 입력하세요.';" onfocus="if(this.value=='메세지를 입력하세요.') this.value='';">
<div style=padding:3px;font-size:10px;>
투명도 : <select id=selalpha name=selalpha  style=font-size:8px; onchange="parent.sock.onalpha(this);cci.focus();">
<option value=100>100%</option>
<option value=90>90%</option>
<option value=80>80%</option>
<option value=70>70%</option>
<option value=60>60%</option>
<option value=50>50%</option>
<option value=40>40%</option>
<option value=30>30%</option>
<option value=20>20%</option>
</select>
색상 :
<select id=selcolor name=selcolor  style=font-size:10px; style="background-color=000000;color=white;" onchange='parent.sock.oncolor(this);cci.focus();'>
<option value="#000000" style=background-color=000000>   </option>
<option value="#00007F" style=background-color=00007F>   </option>
<option value="#009300" style=background-color=009300>   </option>
<option value="#FF0000" style=background-color=FF0000>   </option>
<option value="#7F0000" style=background-color=7F0000>   </option>
<option value="#9C009C" style=background-color=9C009C>   </option>
<option value="#D5AAEB" style=background-color=D5AAEB>   </option>
<option value="#E7E138" style=background-color=E7E138>   </option>
<option value="#FC7F00" style=background-color=FC7F00>   </option>
<option value="#AA6600" style=background-color=AA6600>   </option>
<option value="#00FC00" style=background-color=00FC00>   </option>
<option value="#009393" style=background-color=009393>   </option>
<option value="#00FFFF" style=background-color=00FFFF>   </option>
<option value="#0000FC" style=background-color=0000FC>   </option>
<option value="#FF00FF" style=background-color=FF00FF>   </option>
<option value="#7F7F7F" style=background-color=7F7F7F>   </option>
<option value="#D2D2D2" style=background-color=D2D2D2>   </option>
</select>
</div>
</div>
</div>

<script>
var cr = document.getElementById('chatroom');
var cri = document.getElementById('chatroominner');
var crt = document.getElementById('titlebar');
var cv = document.getElementById('chatview');
var ca = document.getElementById('selalpha');
var cc = document.getElementById('selcolor');
var cci = document.getElementById('chatcontent');

// autoscroll
window.setInterval(function()
{
 if(target) return;
 if(cr) cr.style.top = parseInt(parseInt(cr.style.top) + 0.1 * (parseInt(document.body.scrollTop) + parent.sock.chaty - parseInt(cr.style.top)));
// if(cr) cr.style.top = parseInt(parseInt(cr.style.top) + 0.1 * (parseInt(document.body.scrollTop) + 270 - parseInt(cr.style.top)));
},10);

function chat_close()
{
 parent.sock.chat_closed = !parent.sock.chat_closed;
 if(parent.sock.chat_closed)
 {
  cr.style.display = 'none';
 }
 else
 {
  cr.style.display = 'block';
 }
 window.setTimeout('cv.scrollTop = cv.scrollHeight;',100);
}

function chat_hide()
{
 parent.sock.hide = !parent.sock.hide;
 if(parent.sock.hide)
 {
  cri.style.display = 'none';
  cv.style.height=0;
 }
 else
 {
  cri.style.display = 'block';
  cv.style.height = 170;
 }
}

function addOnLoad(func)
{
 var oldonload = window.onload;
 if (typeof window.onload != 'function') {
  window.onload = func;
 }
 else {
  window.onload = function() {
  oldonload();
  func();
  }
 }
}
function chat(f)
{
 if(parent.sock)
 if(parent.sock.sock)
 if(parent.sock.sock.sendIt)
 {
  var str = f.value.replace('|','');
  parent.sock.sock.sendIt('chat|'+mem_id+'|'+mem_name+'|'+str+'|'+parent.sock.col);
  f.value = '';
 }
}
addOnLoad(function(){
 if(parent.sock)
 {
  // 이미 saved에는 많은 것들이 추가되어있을 것이다.
  if(parent.sock.saved)
  {
  while (cv.hasChildNodes()) cv.removeChild(cv.firstChild);
  var p = document.createElement('div');
  p.innerHTML = parent.sock.saved;
  cv.appendChild(p);
  window.setTimeout('cv.scrollTop = cv.scrollHeight;',100);
  }
  parent.sock.update_chatnum();
  for(var i = 0; i < ca.options.length; i++)
  if(ca.options[i].value == parent.sock.alpha) ca.options[i].selected = true;
  parent.sock.onalpha(ca);
  for(var i = 0; i < cc.options.length; i++)
  if(cc.options[i].value == parent.sock.col) cc.options[i].selected = true;
  parent.sock.oncolor(cc);
  cv.style.overflow='auto';

  if(parent.sock.chatx) cr.style.left = parent.sock.chatx;

  parent.sock.hide = !parent.sock.hide;
  chat_hide();

  parent.sock.chat_closed  = !parent.sock.chat_closed;
  chat_close();
 }
});

var sMousePos = {x:0,y:0};
var sTargetPos = {x:0,y:0};
var target = null;
function getMousePos(e)
{
 if(e.pageX || e.pageY) return {x : e.pageX, y : e.pageY};
 return {x : e.clientX + document.body.scrollLeft - document.body.clientLeft,
  y : e.clientY + document.body.scrollTop  - document.body.clientTop};
}
function getElementPos(e)
{
 var left = 0;
 var top  = 0;
 while (e.offsetParent) {left += e.offsetLeft; top += e.offsetTop; e = e.offsetParent;}
 left += e.offsetLeft;
 top += e.offsetTop;
 return {x:left, y:top};
}

function inDiv(x, y, div)
{
 var rt = getElementRect(div);
 if(rt.l > x) return false;
 if(x > rt.r) return false;
 if(rt.t > y) return false;
 if(y > rt.b) return false;
 return true;
}

function getElementRect(e)
{
 var left = 0;
 var top  = 0;
 var e1 = e;
 try
 {
  while (e.offsetParent)
  {
  left += e.offsetLeft;
  top += e.offsetTop;
  e = e.offsetParent;
  }
  left += e.offsetLeft;
  top += e.offsetTop;
 }
 catch(err) {}
 return {l: left, t: top, r: left + e1.offsetWidth, b: top + e1.offsetHeight};
}

document.onmouseup = function(){
 if(target)
 {
  var pt = getElementPos(target);
  parent.sock.chaty = pt.y - document.body.scrollTop;
  parent.sock.chatx = pt.x - document.body.scrollLeft;
 }
 target = null;
};
document.onmousedown = function(e) {
 e = e || window.event;
 var pt = getMousePos(e);
 var p = e.target || e.srcElement;
 if (inDiv(pt.x, pt.y, crt))
 {
  sMousePos = pt;
  target = document.getElementById("chatroom");
  sTargetPos = getElementPos(target);
 }
};
document.onmousemove = function(e) {
 e = e || window.event;
 var pt = getMousePos(e);
 if (inDiv(pt.x, pt.y, crt))
 {
 document.body.style.cursor = 'move';
 }
 else
 {
 document.body.style.cursor = '';
 }
 if(!target) return;
 target.style.left = sTargetPos.x + (pt.x - sMousePos.x);
 target.style.top = sTargetPos.y + (pt.y - sMousePos.y);
};
</script>
<!-- ---------------------------------------------------------------------- -->
 

본 예제에서는 채팅방을 구현하였지만 Flash Socket과 서버간의 통신을 구현한 소스 코드는 다른 프로젝트에서도 사용될 수 있을거에요.

PS. 본 프로그램은 천문노트에서 유환용군과 진행하던 astrowar라는 게임 프로젝트의 부산물입니다.

'인터넷관련' 카테고리의 다른 글

음악/동영상 태그 (embed,object)  (0) 2007.11.27
색상표  (0) 2007.11.27
키보드 단축키  (0) 2007.11.27
각종 스위시 소스모음  (0) 2007.11.27
PC 셀프 테스트 / 자체 문제 진단 및 해결 방법  (0) 2007.11.27
유용한 유틸리티 모음  (0) 2007.11.27
레지스트리 [Tip 모음]  (0) 2007.11.27
포토샵 전문가 되기! 강좌 모음  (0) 2007.11.27
Posted by 알 수 없는 사용자
,