클라이언트입니다.

그냥 Socket이랑 조금 틀립니다.

그냥 소켓은 데이터를 받을 때에
socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
를 등록해서 데이터가 들어오면 함수가 호출되도록 되어 있습니다.

그리고 보낼 때에도 writeUTF어쩌구로 보냅니다.

근데 XMLSocket은 더 간단하게 주고 받을 수 있습니다.

XMLSocket은 저 아래에있는 이벤트를 등록합니다.
xmlsocket.addEventListener(DataEvent.DATA, socketDataHandler);

그리고, 저 함수에서 DataEvent에 있는 data값에 데이터가 들어있습니다.
그냥 출력해주면 돼요-_-;

보낼 때에는 XMLSocket에 있는 send메소드를 이용해서 그냥 보내면 돼요. 아주 간단해요!

클라이언트(FLEX)


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="initApp()">

<mx:Script>
<![CDATA[
private var xmlsocket:XMLSocket;
[Bindable]
public var userId:String;

private function initApp():void {
currentState = "logon";
}

public function logon():void {
userId = tUserId.text;

xmlsocket = new XMLSocket();
xmlsocket.addEventListener(DataEvent.DATA, socketDataHandler);
xmlsocket.connect("localhost", 10001);
xmlsocket.send(userId + "\n");

currentState = "chat";
}

private function socketDataHandler(event:DataEvent) :void {
log.text += event.data;
}

public function send():void {
xmlsocket.send(msg.text + "\n");
msg.text = "";

}
]]>
</mx:Script>

<mx:Panel id="panel" width="100%" height="100%" verticalAlign="middle"
horizontalAlign="center">
<mx:ControlBar id="cb" height="44" />
</mx:Panel>

<mx:states>

<mx:State name="logon">
<mx:AddChild relativeTo="{panel}">
<mx:HBox>
<mx:Label text="User Id:" />
<mx:TextInput id="tUserId" enter="logon()" />
<mx:Button label="Logon" click="logon()" />
</mx:HBox>
</mx:AddChild>
</mx:State>

<mx:State name="chat">
<mx:SetProperty target="{panel}" name="title"
value="접속자 ID : [{userId}]" />
<mx:AddChild relativeTo="{panel}">
<mx:TextArea id="log" width="100%" height="100%" editable="false"
updateComplete="log.verticalScrollPosition=log.maxVerticalScrollPosition;"/>
</mx:AddChild>
<mx:AddChild relativeTo="{cb}">
<mx:HBox width="100%" paddingTop="0" paddingBottom="0">
<mx:TextInput id="msg" enter="send()" width="100%" />
</mx:HBox>
</mx:AddChild>
</mx:State>

</mx:states>

</mx:Application>


머드초보 이 작성.

당신의 의견을 작성해 주세요.

[로그인][오픈아이디란?]

XMLSocket은 뭔가 이상하군요-_-;

그냥 Socket클래스는 그냥 쓰던 소켓같은데 XMLSocket은 삽질한 결과 이상하게 주고 받는 것 같아요.

우선 보낼 때 이상하게 나눠서 보내게 되더라구요.

그리고 \0을 끝으로 인식하는 듯합니다. 그래서 자바서버에서 보낼 때 pw.println("blur~blur~")이렇게 보낼 때에는 blur~blur~\r\n이 가게 되는데 저것이 끝이라고 인식을 못하더라구요.
그래서 보낼 때에는 pw.print("blur~blur~\n\0") 이라고 보내야해요.

그리고,
mudchobo : 안녕하세요\n\0 라고 보내면, 이상하게 나눠서 호출이 되더라구요-_-;
mudchobo : 데이터를 받고, 그다음에 안녕하세요\n\0을 받아요-_-;

왜그럴까요-_-; 어쨌든, 편법으로 만든 채팅프로그램입니다.

서버(JAVA)
ChatServer.java

package com.mudchobo.chat;

import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;

public class ChatServer {

private ServerSocket server;

void startServer() {
try {
server = new ServerSocket(10001);
System.out.println("접속을 기다립니다.");
HashMap<String, PrintWriter> hashMap =
new HashMap<String, PrintWriter>();

while (true) {
Socket sock = server.accept();
ChatThread chatThread =
new ChatThread(sock, hashMap);
chatThread.start();
} // while
} catch (Exception e) {
System.out.println(e);
}
}
public static void main(String[] args) {
ChatServer chatServer = new ChatServer();
chatServer.startServer();
}
}


ChatThread.java
package com.mudchobo.chat;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;

class ChatThread extends Thread {
private Socket sock;
private String id;
PrintWriter pw;
private BufferedReader br;
private HashMap<String, PrintWriter> hashMap;

public ChatThread(Socket sock, HashMap<String, PrintWriter> hashMap)
throws UnsupportedEncodingException, IOException {
this.sock = sock;
this.hashMap = hashMap;

pw = new PrintWriter(
new OutputStreamWriter(sock.getOutputStream(),"UTF-8"));
br = new BufferedReader(
new InputStreamReader(sock.getInputStream(), "UTF-8"));
id = br.readLine();
hashMap.put(id, pw);
broadcast(id + "님이 접속하였습니다.");
System.out.println("접속한 사용자의 아이디는 " + id + "입니다.");
}

public void run() {
try {
String line = null;
while ((line = br.readLine()) != null) {
if (line.equals("/q")) {
break;
} else {
broadcast(id + " : " + line);
}
}
} catch (Exception ex) {
System.out.println(ex);
} finally {
hashMap.remove(id);
broadcast(id + " 님이 접속 종료하였습니다.");
System.out.println(id + " 님이 접속 종료하였습니다.");
try { if (sock != null) sock.close(); } catch (Exception ex) {}
}
}

public void broadcast(String msg) {
Collection<PrintWriter> collection = hashMap.values();
Iterator<PrintWriter> iter = collection.iterator();
while (iter.hasNext()) {
PrintWriter pw = (PrintWriter) iter.next();
pw.print(msg + "\n\0");
pw.flush();
}
}
}

저 부분만 바뀌었어요 ^^

이제 클라이언트로-_-;

머드초보 이 작성.

당신의 의견을 작성해 주세요.

  1. Comment RSS : http://mudchobo.tomeii.com/tt/rss/comment/158
  2. 계인 2007/11/27 11:53  편집/삭제  댓글 작성  댓글 주소

    좋은 정보가 많네요.. 머드초보님을 싸부로 생각하고 이것저것 해보고 있는데.. 제가 *.java 파일의 위치는 어디로 해야 할지 몰라서... 절대경로 ^^; 완전 초보라..ㅠ_ ㅠ

    • 머드초보 2008/01/26 17:39  편집/삭제  댓글 주소

      아...서버쪽에서는 *.java파일을 저위에 package경로에 넣어야되는데요.
      패키지를 만드셔서 com.mudchobo.chat으로 만드셔서 넣으면 되는데요^^
      그냥 패키지안만드시면 위에 package를 없애버리면돼요 ^^
      저 허접해서 싸부로 생각하지마시고 같이 공부하는 동료로 생각해주세요^^
      허접해서 친구한테 맨날 욕먹고 있어요^^
      방문해주셔서 감사해요 ^^

[로그인][오픈아이디란?]

이번에는 클라이언트를 보겠습니다.

참고로 예제로 배우는 플렉스2에 있는 CODE7_13을 참고했습니다.
(틀만 가져다가 썼습니다 ^^)
FLEX3 BETA2에서 테스트해봤습니다.




클라이언트(FLEX)

ChatClient_Flex.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="initApp()">

<mx:Script>
<![CDATA[
private var socket:Socket = new Socket();
[Bindable]
public var userId:String;

private function initApp():void {
currentState = "logon";
}

public function logon():void {
socket = new Socket("127.0.0.1", 10001);
socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
userId = tUserId.text;
socket.writeUTFBytes(userId + "\n");
socket.flush();
currentState = "chat";
}

private function socketDataHandler(event:ProgressEvent) :void {
var str:String = socket.readUTFBytes(socket.bytesAvailable);
trace(str);
trace("음");
var trimstr:String = str.substr(0, str.indexOf("\r\n"));
log.text += trimstr + "\n";
}

public function send():void {
socket.writeUTFBytes(msg.text + "\n");
socket.flush();
msg.text = "";

}
]]>
</mx:Script>

<mx:Panel id="panel" width="100%" height="100%" verticalAlign="middle"
horizontalAlign="center">
<mx:ControlBar id="cb" height="44" />
</mx:Panel>

<mx:states>

<mx:State name="logon">
<mx:AddChild relativeTo="{panel}">
<mx:HBox>
<mx:Label text="User Id:" />
<mx:TextInput id="tUserId" enter="logon()" />
<mx:Button label="Logon" click="logon()" />
</mx:HBox>
</mx:AddChild>
</mx:State>

<mx:State name="chat">
<mx:SetProperty target="{panel}" name="title"
value="접속자 ID : [{userId}]" />
<mx:AddChild relativeTo="{panel}">
<mx:TextArea id="log" width="100%" height="100%" editable="false"/>
</mx:AddChild>
<mx:AddChild relativeTo="{cb}">
<mx:HBox width="100%" paddingTop="0" paddingBottom="0">
<mx:TextInput id="msg" enter="send()" width="100%" />
</mx:HBox>
</mx:AddChild>
</mx:State>

</mx:states>

</mx:Application>

처음에 소켓이 조금 헷깔렸는데-_-; 이제 좀 알것같네요.
우선 아이디를 입력하고 로그인을 클릭하면 logon함수를 실행하는데 socket에 이벤트리스너를 등록해요.
socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
이거를 등록하게 되면, 서버쪽에서 데이터를 받게 되면 이벤트가 발생되는데 socketDatahandler라는 함수를 호출하라는 얘기죠.
서버가 데이터를 던져주게되면 저함수를 호출해서 readUTFBytes를 호출하면 데이터를 받아올 수 있죠.

※readMultiByte(socket.bytesAvailable, "euc-kr") 이렇게하면
서버쪽에서 UTF-8로 안만들어도 되는데요.
UTF-8이 대세기때문에-_-; UTF-8을 활용합시다-_-;


사용자 삽입 이미지

사용자 삽입 이미지



서버
머드초보 이 작성.

당신의 의견을 작성해 주세요.

  1. Comment RSS : http://mudchobo.tomeii.com/tt/rss/comment/153
  2. chichs 2008/03/26 17:29  편집/삭제  댓글 작성  댓글 주소

    안녕하세요~
    블로그에 막 입성한 초보블로거라서 잘몰라 요래저래 하다보니 트랙백이 갔네요;;
    요새 플렉스를 열심히 배우고 있어서..ㅎㅎ
    이 글을 고대로 퍼가려다가;; (그런건안데나;;)

    암튼.. 좋은정보 감사하구요~ 앞으로 자주 올께요^^

    • 머드초보 2008/03/27 08:28  편집/삭제  댓글 주소

      안녕하세요 ^^ 반갑습니다 ^^
      저도 시작한지 이제 겨우 9개월밖에 안되서 ^^
      저는 트랙백거는거 한 3달만에 터득한 것 같은데 대단하십니다 ^^
      글 퍼가셔도 되는데 출처만 남기시면 돼요 ^^
      그럼 앞으로 블로그를 잘 이끌어나가세요 ^^

  3. 낭만공돌이 2008/05/01 01:40  편집/삭제  댓글 작성  댓글 주소

    적어주신 예제. 간단하고 이해하기 쉬워서 너무 잘 보았습니다!
    다만 한가지 질문이 있는데.
    client 단에서 첫번째로 보낸 메시지를 userID 로 받아서 "접속한 사용자의 ID는 xxx 입니다."
    라고 뿌려주시는 것 같은데.

    저는 아무래도 그 첫번째 메시지가 계속
    <policy-file-request/>
    인 것 같습니다.
    덕분에 첫번째 채팅 메시지가 ID로 인식되는군요 ㅠ

    이거 어떻게 해야 해결될까요..

    인터넷을 뒤져서
    classdomain.xls 파일을 만들라는 조언도 봤는데, 그대로 해도 잘 안되는군요;;;;
    ㅠㅠ

    혹시 도와주실 수 있을까요...ㅠ

    • 머드초보 2008/05/07 18:07  편집/삭제  댓글 주소

      아....무슨얘기인지 잘 모르겠네요-_-;
      접속한 아이디라면...아이디를 그냥 서버에 넘겨주면 될듯한데요
      서버단에서 처리해야할 듯 합니다 ^^

  4. jun 2008/06/02 18:53  편집/삭제  댓글 작성  댓글 주소

    crossdomain 문제입니다 ..

    서버단에서 크로스 도매인 문서를 보내주고

    서버에서 접속을 끊어야 합니다

  5. calmtot 2009/03/06 16:42  편집/삭제  댓글 작성  댓글 주소

    좋은 정보 잘 보고 갑니다~~ 고마워요 ^^ ㅋ

  6. 김경순 2009/03/10 16:02  편집/삭제  댓글 작성  댓글 주소

    고맙습니다. 저도 플랙스 채팅 프로그램을 Client/Server로 만드는 중인데 좋은 자료여서
    참고하도록 하겠습니다. 감사합니다.

[로그인][오픈아이디란?]