정보를 보낼때 헤더는 참 유용하고 필수적이다. 편지를 쓴다고 생각하자면, 받는사람 , 주소 , 우편번호 등등이 헤더에
해당할것이고 , 동내 구멍가게에서 라면을 사더라도 , 이라면이 무슨라면인지 , 매운맛인지 순한맛인지 ,조리법은 어떻
게 되는지 등등이 해더에 해당하는 정보라고 생각한다.
이처럼 무언가를 보낼때 이것이 어떠한 것이다 라는것을 표현할때는 조금은 바이트 배열을 이해할 필요가 있다.
as3 에서는 ByteArray에 해당할것이고 , c# 에서는 Stream 등에 해당할것이다.
그리고 해더는 Text로 읽을수 있는 정보일것이고, (물론 어느 오브젝트 바이트 배열로 하겠다면 구지 텍스트가 아니어도 된다. ) 컨텐츠 영역은 Text일수도 있고 바이너리 일수도 있다.
문제는 없다. 뭐 어찌되었든 바이트로 넘어오고 약속된 영역을 텍스트로 치환하느냐, 바이너리로 통과 시키냐의 차이이다.
아래의 그림은 헤더를 보내는 한가지 아이디어가 될것이다. 무조건 0바이트 부터 128 바이트까지 텍스트로 된 헤더라고 가정하고 있다. 혹 헤더가 128이 채워지지 않았다면 인위적으로 채워 버려 꼭 128을 만들어 버린다. ( 내가 생각하는 헤더에는 경로 , 타입, 기타코멘트 등등해서 128바이트면 충분하다고 생각해서 128이라고 한것, 그뿐이다.)
그리고 129번째 바이트 부터는 원하는 내용을 채우면 된다.
(이러한 해더의 아이디어를 발전시키고 싶다면 유명한 포토샵파일 PSD 의 바이트코드를 분석해 보라. 기가막히게 순수하고 심플하게 되어 있다.)
그럼 위의 그림을 토대로 코드를 한번 보자
As3 에서 헤더 정보로 경로를 Text형대로 보내고 나머지는 카메라에서 캡쳐 받은 png포멧을 보낸다.
c#은 헤더로 넘어온 것을 FileStream의 경로로 지정하고 내용을 해당 경로에 저장한다.(버퍼의 사용은 이전글을 참고)
c# 서버
using System;
using System.Windows;
using System.Net.Sockets;
using System.Threading.Tasks;
using System.IO;
using System.Net;
using System.Text;
namespace testEncoderRecieve
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
}
private Task ServerThread;
private TcpListener server;
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
ServerThread = new Task(startServerThreaed);
server = new TcpListener(System.Net.IPAddress.Parse("127.0.0.1"),5555);
//
ServerThread.Start();
}
void startServerThreaed()
{
//서버 스레드가 시작되고 서버가 시작되었다.
Console.WriteLine("startServerThread");
server.Start();
//컨텐츠 버퍼와 헤더버퍼를 생성하였다.
Byte[] buffer = new Byte[64];
Byte[] headerBuffer = new Byte[128];
int testCount = 0;
while (true)
{
TcpClient client = server.AcceptTcpClient();
NetworkStream netStream = client.GetStream();
//netStream 에서 지정된 해더 바이트버퍼 만큼읽어서
//해더정보를 입수한다.
//그리고 netStream의 포지션은 128 이 되었다.
netStream.Read(headerBuffer, 0, headerBuffer.Length);
String rowHeader = Encoding.ASCII.GetString(headerBuffer);
//String.Trim 을 이용해 불필요한 공백을
//제거하고 딱 필요한 헤더만 추출했다.
string header = rowHeader.Trim();
FileInfo fInfo = new FileInfo(header);
//이전과 같이 파일 스트림을 생성하였고,
//파일경로로는 헤더에서 넘어온 정보를 사용하였다.
//그리고 여기서 읽을 netStream의 포지션은 129부터 이다.
FileStream fs = new FileStream(fInfo.FullName, FileMode.OpenOrCreate, FileAccess.Write);
int i = 0;
while ((i = netStream.Read(buffer, 0, buffer.Length)) > 0)
{
fs.Write(buffer, 0, i);
}
fs.Close();
netStream.Close();
client.Close();
++testCount;
}
}
}
}
|
as3 클라이언트
package {
import flash.events.Event;
import flash.net.Socket;
import flash.utils.ByteArray;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.media.Camera;
import flash.media.Video;
/**
* @author superSc_PC
*/
[SWF(width = "1000")]
public class Main extends Sprite
{
private var cam : Camera;
private var vid : Video;
private var captureBitmap : Bitmap;
private var socket : Socket;
private var headerBufferSize : int = 128;
private var header : ByteArray = new ByteArray();
private var captureByte : ByteArray;
public function Main()
{
//필요한것들을 생성했다.
cam = Camera.getCamera();
vid = new Video();
vid.attachCamera(cam);
captureBitmap = new Bitmap(new BitmapData(vid.width, vid.height));
captureBitmap.x = vid.width;
addChild(vid);
addChild(captureBitmap);
stage.addEventListener(MouseEvent.CLICK , takePic);
socket = new Socket();
socket.addEventListener(Event.CONNECT, connectFn);
//header 에 필요한정보를 입력하였다.
//그리고 바이트의 공백을 매꾸기 위해 while루프로 쓰레기 정보들을
//입력하였고 마지막 바이트로 줄바꿈"\n"을 입력 하였다.
header.writeUTFBytes("d:/testAS.png");
while(header.position < headerBufferSize-1)
{
header.writeUTFBytes(" ");
}
header.writeUTFBytes("\n");
}
private function connectFn(event : Event) : void {
if (captureByte != null && captureByte.length > 0)
{
//이전과 다르게 소켓에 연달아 2개의 바이트들을 보낸다.
//처음에는 헤더정보를 다음엔 캡쳐된 png를 보낸다.
//역시나 보내고 난뒤에 소켓을 죽인다.
socket.writeBytes(header);
socket.writeBytes(captureByte);
socket.flush();
socket.close();
}
}
private function takePic(event : MouseEvent) : void {
captureBitmap.bitmapData.draw(vid);
captureByte = PngEncoder.encode(captureBitmap.bitmapData);
captureByte.position = 0;
if(socket.connected == false)
{
socket.connect("localhost", 5555);
}
}
}
}
|
댓글을 달아 주세요
이용약관위배로 관리자 삭제된 댓글입니다.
이용약관위배로 관리자 삭제된 댓글입니다.
이용약관위배로 관리자 삭제된 댓글입니다.
이용약관위배로 관리자 삭제된 댓글입니다.
이용약관위배로 관리자 삭제된 댓글입니다.
이용약관위배로 관리자 삭제된 댓글입니다.
이용약관위배로 관리자 삭제된 댓글입니다.
이용약관위배로 관리자 삭제된 댓글입니다.
이용약관위배로 관리자 삭제된 댓글입니다.
이용약관위배로 관리자 삭제된 댓글입니다.
이용약관위배로 관리자 삭제된 댓글입니다.
이용약관위배로 관리자 삭제된 댓글입니다.
이용약관위배로 관리자 삭제된 댓글입니다.
이용약관위배로 관리자 삭제된 댓글입니다.
이용약관위배로 관리자 삭제된 댓글입니다.
이용약관위배로 관리자 삭제된 댓글입니다.
이용약관위배로 관리자 삭제된 댓글입니다.
이용약관위배로 관리자 삭제된 댓글입니다.
이용약관위배로 관리자 삭제된 댓글입니다.
리있大话西游服务端凡人修真服务端大话西游服务端页游服务端问道服务端
跑跑卡丁车服务端英雄远征服务端幻灵游侠私服务端洪荒神话私服务端
完美世界服务端烈焰服务端洛汗服务端新魔界服务端绝对女神私服务端
魔兽私服开区一条龙服务-
传奇私服开传奇一条龙服务-
传奇广告代理-
IDC服务器以及空间租用-
魔域开区sf一条龙开区服务-
客服咨询QQ(企鹅扣扣)1325876192
Email:1325876192@qq.com
商业版本免费开放下载
紫川科技最新毁灭天下1.85狂雷独家合击热血复古三职业新装传奇服务端
紫川科技20星大极品良装+80麒麟锻造中变传奇服务端
紫川科技独家轻变1.89奥妙转生神龙锻造珍珑元素版传奇服务端
紫川科技独家九转1.85四皇冠加倍装备特戒龙卫다니