많은 분들(?)이 제 블로그에 오셔서 질문을 해주셔서 간단한 예제를 통한 설명을....-_- 나중에 저도 참고하려고 기록용-_-
일단, Flash에서 CrossDomain에 걸리는 데이터를 요청할 때 Plicy File인 crossdomain.xml 파일을 root에 정의해둬서 해당 도메인이면 데이터를 허용하게 할 수 있습니다.
소켓도 마찬가지입니다. 해당 도메인에서 해당 포트로 들어온 요청은 받겠다는 정책파일을 작성할 수 있습니다.
최초 소켓이 정책파일을 요청하게 되는 포트는 843포트입니다. 만약 이포트가 열러있지 않다면 현재 연결하려고 하는 포트로 <policy-file-request/>를 날려서 정책파일을 요청하게 됩니다.
그러면 843이든, 해당포트든 간에 정책파일만 날려주면 됩니다.
[code]<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="*" to-ports="10000-10001" />
</cross-domain-policy>[/code]
소켓에 대한 정책파일을 정의한 것인데, domain에는 허용할 도메인을 쓰고, to-ports에는 허용할 포트를 쓰면 됩니다.
이걸 날려주면 이제 연결할 포트로부터 데이터를 주고 받을 수 있습니다.
초간단 에코예제!
일단 서버는 자바로...(그나마 자신있는 언어라서ㅠㅠ)
일단 PlicyFileServer를 하나 돌릴 쓰레드를 만듭니다.
PlicyFileServer.java
[code]import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class PolicyFileServer extends Thread{
private ServerSocket serverSocket;
private String policyFile = "<?xml version='1.0'?>" +
"<!DOCTYPE cross-domain-policy SYSTEM '/xml/dtds/cross-domain-policy.dtd'>" +
"<cross-domain-policy>" +
"<allow-access-from domain='*' to-ports='10000' />" +
"</cross-domain-policy>";
@Override
public void run() {
try {
serverSocket = new ServerSocket(843);
while (true) {
final Socket socket = serverSocket.accept();
new Runnable() {
@Override
public void run() {
try {
socket.setSoTimeout(10000);
InputStream in = socket.getInputStream();
byte[] buffer = new byte[23];
if ( in.read(buffer) != -1 && (new String(buffer)).startsWith("<policy-file-request/>") ) {
OutputStream out = socket.getOutputStream();
out.write(policyFile.getBytes());
out.write(0x00);
out.flush();
out.close();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try { socket.close();} catch(Exception ex){}
}
}
}.run();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
[/code]
내용을 보면 그냥 서버소켓하나 만들어서 요청이 들어오면 그 소켓으로 policy file을 전송하는 형태입니다. 파일은 만들기 귀찮아서-_- 그냥 String으로 선언-_- 보면 모든도메인에 한해서 10000포트를 열어주는 겁니다.
이제 메인서버!
SocketTest.java
[code]import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class SocketTest {
private ServerSocket server;
public SocketTest() {
try{
server = new ServerSocket(10000);
System.out.println("접속을 기다립니다.");
while (true){
final Socket socket = server.accept();
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
PrintWriter pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8"));
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println("수신데이터 : " + line);
pw.println("Hello! " + line);
pw.flush();
}
} catch (Exception e) {
try { if(socket != null) socket.close(); } catch (Exception ex) {}
}
}
});
t.start();
}
} catch(Exception e){
System.out.println("Error!");
}
}
public static void main(String[] args) {
new PolicyFileServer().start();
new SocketTest();
}
}[/code]
데이터를 받으면 다시 Hello!를 붙여서 다시 전송해주는 echo서버를 하나 만듭니다.
그리고 main함수에서는 PolicyFileServer쓰레드를 하나 시작하고, EchoServer를 돌립니다.
이제 Flex!
[code]<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
applicationComplete="application1_applicationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import spark.components.mediaClasses.VolumeBar;
private var socket:Socket;
protected function application1_applicationCompleteHandler(event:FlexEvent):void
{
socket = new Socket("127.0.0.1", 10000);
socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
socket.addEventListener(Event.CONNECT, connectHandler);
}
protected function btnSend_clickHandler(event:MouseEvent):void
{
// TODO Auto-generated method stub
socket.writeUTFBytes(inputMessage.text + "\n");
socket.flush();
}
private function connectHandler(event:Event):void
{
trace("접속완료!");
hbox.visible = true;
}
private function socketDataHandler(event:ProgressEvent):void
{
var message:String = socket.readUTFBytes(socket.bytesAvailable);
trace("수신메세지 : " + message);
textResult.text = message;
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:layout>
<s:VerticalLayout />
</s:layout>
<mx:HBox id="hbox" visible="false" width="100%" horizontalAlign="center">
<s:TextInput id="inputMessage" />
<s:Button id="btnSend" label="송신하기" click="btnSend_clickHandler(event)"/>
</mx:HBox>
<mx:Text id="textResult" width="100%" textAlign="center"/>
</s:Application>
[/code]
Socket만들어서 10000포트로 연결합니다. 그러면 도메인이 다르게 되면 swf가 843포트로 "<policy-file-request/>"를 날려서 정책파일을 달라고하는데, 서버에서 만들어놓은 PolicyFileServer가 정책파일을 내려주면 받게되면 10000포트로 다시 연결해 연결을 시작하게 됩니다.
몬가 별거 없는데 장황하게 설명해놨네.
그리고, 이런식으로 PolicyFileServer를 서버어플에 통합하면 안되겠죠? 나중에 서버어플이 늘어난다면 계속 새로 추가해야하니, PolicyfileServer를 따로 만들어서 띄워놓으면 되겠죠?^^
일단, 여러 폴리시서버 예제는 구글링하면 많이 나와요~
여기 아래주소는 Java, PHP, C#, VB.NET, Python 등등 예제가 있어요.
http://code.google.com/p/assql/wiki/SecurityInformation이건 c로 만든거!
http://panzergruppe.hp.infoseek.co.jp/fspfd.html