설명) Form에 테트리스게임이 수행되고 인는중이라도, 백그라운드로 쓰레드 2개가 현재 동작하는 모습을 나타냅니다.
여러모로 실전활용가능한 모델입니다.

1. Form Activate & Other Statistic Possible(Threading Background)
2. BackgroundWorker
3. Form Drawing
4. Data set,get
5. Tris
6. Form - WM_PAINT Logic

basic !!

ex11.cs
0.01MB

Background class
Tris class divide!!!

ex12.cs
0.01MB

static class ----> #define instead!!

ex13.cs
0.01MB

design pattern various!!

ex14.cs
0.01MB

/*
 * BackgroundWorker 사용법 : Form 혹은 Console이 사라지면 함께 작동을 멈춘다.
 * BackgroundWorker 클래스
   네임스페이스: System.ComponentModel
 */


using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Threading;

public class Program : Form
{
int toggle=0;

public Program()
{
this.Text="BackgroungWorker Thread Process!!";
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if ((msg.Msg == WM_KEYDOWN) || (msg.Msg == WM_SYSKEYDOWN))
{
         switch (keyData)
         {
         case Keys.S:
             break; 
         case Keys.F5:
             break; 
         case Keys.Enter:
             Application.Exit();
             break;
         case Keys.Tab:
             break;
         default:
             break;
         }
     }
return base.ProcessCmdKey(ref msg, keyData);
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);

try
{
switch(m.Msg)
{
default:
if(toggle==0)
{
BackgroundMakeCls nm = new BackgroundMakeCls();
nm.running();

toggle=100; //Form이 실행시에 오직 한번만 수행하도록 한다.
}
break;
}
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
public static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Program());
}
}

public class BackgroundMakeCls
{
BackgroundWorker recvWorker = new BackgroundWorker();
BackgroundWorker sendWorker = new BackgroundWorker();

public void running()
{
recvWorker.DoWork += new DoWorkEventHandler(recvWorker_DoWork);
recvWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(recvWorker_RunWorkerCompleted);

sendWorker.DoWork += new DoWorkEventHandler(sendWorker_DoWork);
sendWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(sendWorker_RunWorkerCompleted);

recvWorker.RunWorkerAsync();
}
void recvWorker_DoWork(object sender, DoWorkEventArgs e)
{
Console.WriteLine(">>>>recvWorker_DoWork");
}
void recvWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
Console.WriteLine(">>>>recvWorker_RunWorkerCompleted");

try
{
if(! sendWorker.IsBusy) sendWorker.RunWorkerAsync();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
void sendWorker_DoWork(object sender, DoWorkEventArgs e)
{
Console.WriteLine(">>>>recvWorker_DoWork");
}
void sendWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Console.WriteLine(">>>>recvWorker_RunWorkerCompleted");

try
{
if(! recvWorker.IsBusy) recvWorker.RunWorkerAsync();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}

[Redis] BLPOP

Blocking 된 상태에서 list를 pop 하는 것을 말한다. LPOP의 blocking 버전이라고 할 수 있다.
BLPOP가 호출이 되면, list의 헤더에 있는 key 값이 호출된다.

redis> BLPOP list1 list2 list3 0

list1, list2, list3에 존재하는 키 값중 가장 먼저 쓰여진 list1에 저장된 키 값 하나를 pop 한다.
list1에 값이 없다면 list2의 값을 pop 한다.
만약 list1, list2, list3 모두 값이 없다면 redis는 다른 client에서 해당 list에 값을 입력하기 전까지는 block 된다.
(맨 마지막 0은 timeout 파라미터로써 0일 경우엔 INFINITE, 그 외엔 초단위의 타임 아웃 값을 가짐)

redis> RPUSH list1 a b c d e
(integer) 5
redis> RPUSH list2 1 2 3 4 5
(integer) 5
redis> BLPOP list1 list2 0
1)"list1"
2)a
redis> BLPOP list2 0
1)"list2"
2)1

C#)

DataEncoding ____dataEncode = new DataEncoding();
try
{
byte[][] jsonByte = null; jsonByte=____receiveRedis.BLPop("KEYNAME",10);
for(ii=1; ii<jsonByte.Length; ii++)
{
byte[] jsonEachByte = new byte[jsonByte[ii].Length];
Console.WriteLine(____dataEncode.EncodingByteToStr(jsonEachByte));
}
}

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;


class Program
{
public static void Main(string[] args)
{
ContinueNoLoginCls nm = new ContinueNoLoginCls();
nm.running();
}
}

class ContinueNoLoginCls
{
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool PostMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

[DllImport("user32.dll")]
static extern int SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

[DllImport("User32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[DllImport("User32.dll")]
public static extern IntPtr FindWindowEx(int hWnd1, int hWnd2, string lpClassName, string lpWindowName);

const uint WM_KEYDOWN = 0x0100;
const uint WM_KEYUP = 0x0101;
const uint WM_CHAR = 0x0102;
const int VK_TAB = 0x09;
const int VK_ENTER = 0x0D;
const int VK_UP = 0x26;
const int VK_DOWN = 0x28;
const int VK_RIGHT = 0x27;
const int VK_F5 = 0x74;
const int VK_F6 = 0x75;
 
//According to SPY++ in IE

//ENTER key is
// P KEYDOWN
// P CHAR
// S CHAR
// P KEY_UP

//TAB key is
// P KEYDOWN
// P KEYUP

//DOWN, UP, RIGHT, LEFT is
// P KEYDOWN
// S KEYDOWN
// P KEYUP

//Letters is
// P KEYDOWN
// S KEYDOWN
// P CHAR
// S CHAR
// P KEYUP

IntPtr tailHandle = IntPtr.Zero;
IntPtr Handle_1 = IntPtr.Zero;
IntPtr Handle_2 = IntPtr.Zero;
//const string captionmsg="파일 탐색기";
//const string captionmsg="명령 프롬프트";
const string captionmsg="네이버 부동산 - Microsoft Edge";

public void running()
{
Console.Title = "";
tailHandle = FindWindow(null, captionmsg);

ConsoleKeyInfo keyinfo;

while(true)
{
keyinfo=Console.ReadKey(true);

debug(">>>>KEY:[" + keyinfo.Key.ToString() + "]");

if(keyinfo.Key==ConsoleKey.Enter)
{
debug(">>>>SendTab() method call!!");
SendTab();
}
else if(keyinfo.Key==ConsoleKey.RightArrow)
{
debug(">>>>SendArrowKey() method call!!");
SendChar(VK_F5);
}
else if(keyinfo.Key==ConsoleKey.Spacebar)
{
debug(">>>>SendArrowKey() method call!!");
SendArrowKey(VK_F5);
}

else if(keyinfo.Key==ConsoleKey.Escape)
{
debug(">>>>Quit() method call!!");
break;
}
}
}

void debug(string str)
{
Console.WriteLine(str);
}

    private void SendEnter()
    {
        PostMessage(tailHandle, WM_KEYDOWN, (IntPtr)VK_ENTER, IntPtr.Zero);
        PostMessage(tailHandle, WM_CHAR, (IntPtr)VK_ENTER, IntPtr.Zero);
        SendMessage(tailHandle, WM_CHAR, (IntPtr)VK_ENTER, IntPtr.Zero);
        PostMessage(tailHandle, WM_KEYUP, (IntPtr)VK_ENTER, IntPtr.Zero);
    }

    private void SendTab()
    {
        PostMessage(tailHandle, WM_KEYDOWN, (IntPtr)VK_TAB, IntPtr.Zero);
        PostMessage(tailHandle, WM_KEYUP, (IntPtr)VK_TAB, IntPtr.Zero);
    }

    private void SendArrowKey(int key)
    {
        PostMessage(tailHandle, WM_KEYDOWN, (IntPtr)key, IntPtr.Zero);
        SendMessage(tailHandle, WM_KEYDOWN, (IntPtr)key, IntPtr.Zero);
        PostMessage(tailHandle, WM_KEYUP, (IntPtr)key, IntPtr.Zero);
    }

    private void SendChar(int key)
    {
        //Keydown wParam values are 0x020 less than WM_CHAR wParam
        PostMessage(tailHandle, WM_KEYDOWN, (IntPtr)(key - 0x020), IntPtr.Zero);
        SendMessage(tailHandle, WM_KEYDOWN, (IntPtr)(key - 0x020), IntPtr.Zero);
        PostMessage(tailHandle, WM_CHAR, (IntPtr)key, IntPtr.Zero);
        SendMessage(tailHandle, WM_CHAR, (IntPtr)key, IntPtr.Zero);
        PostMessage(tailHandle, WM_KEYUP, (IntPtr)(key - 0x020), IntPtr.Zero);
    }
}



Assembly.LoadFrom() : DLL 활용하여, Form을 띄우기
/*----------------------------------------------------------------------
Description : 클래스라이브러리로 생성되어진 폼을 띄울때에 사용되어진다.(폼형태만 가지고 인는것을 폼처럼 만들어서 띄울수있다.)
ex) 
1. frm's name : UAPDBMQ0010
2. dll's name : DBM.DLL
----------------------------------------------------------------------*/

sample code>>

string formName = "UAPDBMQ0010";
string dllName = formName.Substring(3,3); //DBM.DLL
string assembly = dllName + ".DLL";
string classname = dllName + "." + formName;

Assembly asm = Assembly.LoadFrom(assembly);
object o = asm.CreateInstance(classname);
var doc = (Form)o;

Form frm = doc;
frm.Tag = assembly;
if(frm == null) return null;

frm.MdiParent = this; //MDI CASE
frm.FormBorderStyle = FormBorderStyle.None; //NEW FORM
frm.Dock = DockStyle.Fill //POPUP, WHEN DELETE

frm.Text="";
frm.TopLevel=false;
frm.Parent=this;
frm.Show();

>>>>> .bashrc 와 .bash_profile 의 차이

1) bash 쉘(Shell) 이란?
쉘(Shell)은 운영체제에서 **사용자가 입력하는 명령을 읽고 해석하여 대신 실행해주는 프로그램**입니다. 
운영체제 상에서 다양한 운영체제 기능과 서비스를 구현하는 인터페이스를 제공하며, 사용자와 운영체제의 내부(커널)` 사이의 인터페이스를 감싸는 층이기 때문에 셸이라는 이름이 붙었습니다. 
쉘은 운영체제에서 필수적으로 존재합니다.

운영체제는 로그인한 사용자가 없다면 하나의 쉘도 실행되지 않은 상태이며, 
사용자가 로그인을 시도하면 운영체제는 ID와 패스워드를 받아들이는 로기은 프로그램을 실행하고, 
사용자가 입력한 ID와 패스워드를 검증한 후 인증된 사용자라면 쉘을 실행하여 사용자 세션을 쉘에게 전달합니다.

쉘의 역할은 사용자가 입력한 명령을 해석하여 대신 실행해주는 것입니다. 
쉘의 내부 명령어라면 스스로 실행한 뒤 화면에 표시해주고 내부 명령어가 아니라면 PATH 환경변수에 
지정된 경로에서 입력받은 명령과 같은 파일을 찾아 exec() 시스템콜을 호출하여 실행한 뒤 
키보드와 마우스 등의 입력장치와 모니터에 해당하는 표준 출력장치의 제어권을 해당 프로그램에 넘겨준 뒤 프로그램이 끝날 때 까지 대기하는 역할을 합니다.

bash 쉘은 유닉스에서 사용하는 커맨드 쉘의 일종으로 GNU 프로젝트를 위해 만들어졌습니다. 
초기의 유닉스 쉘인 본 쉘(Bourne Shell)과 새로 태어났다는 뜻의 영어 ‘born again’을 합쳐 **본 어게인 쉘(Bourne-again Shell)**이라고 불렸으나, 
일반적으로 bash로 줄여 부릅니다.

2) Login Shell 과 Non-Login Shell

Login Shell
Login은 ID와 패스워드를 입력해서 Shell을 실행하는 것을 말합니다. 따라서 ssh로 접속하거나 로컬에서 GUI를 통해 Shell을 실행하는 것은 Login Shell 입니다.
.profile, .bash_profile 이 두 파일은 Login할 때 로드되는 파일입니다. .profile은 꼭 bash가 아니더라도 로그인하면 로드되며, .bash_profile은 꼭 bash로 로그인 할 때만 실행됩니다.

Non-Login Shell
Non-Login Shell은 로그인 없이 실행하는 Shell을 말합니다. ssh로 접속하고 나서 다시 bash를 실행하는 경우나, GUI 세션에서 터미널을 띄우는 것도 여기 해당합니다. ‘sudo bash’나 ‘su’같은 것도 해당합니다.

.bashrc 와 .bash_profile 의 차이
.bashrc
이미 로그인 한 상태에서 새 터미널 창을 열 때마다 로드됩니다. (Non-Login Shell에서 실행됩니다.)

.bash_profile
시스템에 로그인할 때마다 로드됩니다. (Login Shell에서 실행됩니다.) 대부분 개별 사용자에 대한 설정에 대한 코드들이 들어갑니다. 예를 들면 nvm(Node Version Manager)은 기본적으로 nvm을 사용하지 않고 Node를 설치할 때와는 다르게 각 사용자의 경로에 설치되게 되는데, 이럴때 nvm의 PATH를 .bash_profile 파일에 기재합니다.

.profile
로그인할 때 로드됩니다. 개별 사용자에 대한 설정 코드들 중 bash와는 관계없는 부분을 기재합니다.

만약 Mac에서 새 터미널 창을 열 때마다 .bashrc를 로드하고 싶다면 .bash_profile에서 .bashrc를 로드하면 됩니다.

# Source bashrc
if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi

[C#] PDB(*.pdb) 파일(?)

PDB 파일이란 무엇이며 솔루션을 다시 빌드 할 때 릴리스 폴더에서 PDB 파일을 어떻게 제외시킬 수 있습니까?

PDB 파일에는 디버거가 작업 할 정보가 들어 있습니다. 
릴리스 빌드에는 디버그 빌드보다 정보가 적습니다. 
그러나 전혀 생성하지 않으려면 프로젝트의 빌드 속성으로 이동하여 릴리스 구성을 선택하고 “고급 …”을 클릭 한 다음 
"디버그 정보"에서 "없음"을 선택하십시오.

오늘까지는 Exception.StackTrace예외를 해결하는 데 필요한 파일 및 줄 번호 정보가없는 메시지 상자에 왜 누락 되었는지 알아 내려고 시도 할 때까지 모든 것이 제대로 작동했습니다 . 
이 게시물을 다시 읽고 중요한 정보를 발견했습니다 
.PDB는 앱을 실행하는 데 필요하지 않지만 파일과 줄 번호가 StackTrace문자열 에 있어야 합니다. 
PDB 파일을 실행 가능 폴더에 포함 시켰으며 이제는 모두 정상입니다.

PDB 는 P rogram D ata B ase 의 약자입니다. 
이름에서 알 수 있듯이 프로그램을 디버그 모드로 실행하는 데 필요한 정보를 유지 관리하는 저장소 (데이터베이스와 같은 영구 저장소)입니다. 
여기에는 코드를 디버깅하는 동안 (Visual Studio에서) 디버거가 Visual Studio에서 중단 될 것으로 예상되는 지점을 삽입 한 지점과 같은 중요한 관련 정보가 많이 포함되어 있습니다.

*.pdb디버그 폴더에서 파일 을 제거하면 Visual Studio가 중단 점에 여러 번 실패하는 이유 입니다. Visual Studio 디버거는 파일을 사용하여 스택 추적에서 예외가 발생한 정확한 줄 번호의 코드 파일을 알려줄 수도 *.pdb있습니다. 따라서 효과적으로 pdb 파일은 프로그램을 디버깅하는 동안 개발자에게 큰 도움이됩니다.

일반적으로 *.pdb파일 생성을 제외하지 않는 것이 좋습니다 . 
프로덕션 릴리스 관점에서해야 할 일은 pdb 파일을 작성하지만 제품 설치 프로그램의 고객 사이트에는 제공하지 않는 것입니다. 
생성 된 모든 PDB 파일을 필요한 경우 나중에 사용 / 참조 할 수있는 기호 서버에 보존하십시오. 
특히 프로세스 충돌과 같은 문제를 디버깅하는 경우에 적합합니다. 
크래시 덤프 파일 분석을 시작하고 *.pdb빌드 프로세스 중에 만들어진 원본 파일이 유지되지 않으면 Visual Studio에서 크래시를 일으키는 정확한 코드 줄을 만들 수 없습니다 .

PDB 파일은 디버거에 의해 사용되는 정보가 포함되어 있습니다. 
응용 프로그램을 실행할 필요가 없으며 릴리스 된 버전에 포함시킬 필요가 없습니다.

Visual Studio에서 pdb 파일이 생성되지 않도록 설정할 수 있습니다. 
명령 행 또는 스크립트에서 빌드하는 경우 /Debug스위치 를 생략하십시오.


C#프로젝트를 빌드하면, exe 혹은 dll파일과 함께 pdb파일도 함께 나오는 것을 종종 확인하셨을 것입니다.
pdb파일은 프로그램을 디버깅할 때 필요한 파일입니다.
pdb파일 속에는 디버깅에 필요한 정보들이 포함되어 있습니다.
이 말을 뒤집으면 프로그램을 배포할 때에는 pdb파일이 있어선 안 되겠죠.
그래서 혹시 배포 패키지에 pdb파일이 섞여 들어가는 것을 막기 위해 빌드 옵션을 설정할 수가 있습니다.
그럼 지금부터 pdb파일을 나오게 하는 법, 안 나오게 하는법에 대해 알아보도록 하겠습니다.

>>>>PDB파일 안나오게 하는 법

1. 프로젝트 우클릭 2. Properties 클릭 3. 좌측의 Build 클릭 4. Advanced 클릭 5. Debugging information을 Pdb-only로 설정

 


//APM/APMCommManager/APMCommManagerForm.cs
void recvWorker_DoWork(object sender, DoWorkEventArgs e)
{
    byte[][] jsonByte = null;

    jsonByte=____receiveRedis.BLPop("CLI:" + ClientCurrentId.GetInstance.MyId, 10);
    for(ii=1; ii<jsonByte.Length; ii++)
    {
        byte[] ____jsonByte=new byte[jsonByte[ii].Length];
        jsonByte[ii].CopyTo(____jsonByte, 0);

        recvQueue.Enqueue(____jsonByte);// 데이타를 입력한다.

        SendToTail()// 수신받은 데이타를 로그로 기록한다.

        if( ! ____sendClientWorker.IsBusy) ____sendClientWorker.RunWorkerAsync();
    }
}

//APM/APMCommManager/APMCommManagerForm.cs
void ____sendClientWorker_DoWork(object sender, DoWorkEventArgs e)
{
    if(receiveQueue > 0)
    {
        byte[] buffer = receiveQueue.Dequeue(); //데이타를 꺼낸다.
        CheckData(buffer);
    }
}

//APM/APMCommManager/APMCommManagerForm.cs
void CheckData(byte[] buffer)
{
    buffer -> jsonstring;
    PWInterface ifReceive <- jsonstring;

    string[] split = ifReceive.id.Split('.');
    APMApiPublic.send((IntPtr)MetaData.APP_TYPE.NONE,
                          (IntPtr)Convert.ToInt64( split[1] ), buffer); //HANDLE(1)
}


'c# 언어 > 기타' 카테고리의 다른 글

Application.Perfomance.Management(Sending by Redis)  (0) 2022.01.13

Login After,,,,,,,,

Process.Start("APMCommManager.exe");

-APMCommManager.exe

Application.Run(new APMCommManagerForm()); //APMCommManager/Program.cs

public APMCommManagerForm() //APMCommManager/APMCommManagerForm.cs
{
    mainWindowHandle = (IntPtr)Convert.ToInt32( arguments[1] );
    APMApiPublic.PostMessage(Handle, APMApiPublic.UWM_APP_STARTUP, (IntPtr)0, (IntPtr)0 );
}

protected override void WndProc(ref Message m) //APMCommManager/APMCommManagerForm.cs
{
    switch(m.Msg)
    {
        case APMApiPublic.UWM_APP_STARTUP:
        APMApiPublic.SendMessage(mainWindowHandle, APMApiPublic.UWM_APP_STARTUP, (intPtr)Handle, 
        (IntPtr)Process.GetCurrentProcess().id);
        break;
    }
}

-Basic Const Variables
protected override void WndProc(ref Message m) //APM/APMMain.cs
{
    switch(m.Msg)
    {
        case APMApiPublic.UWM_APP_STARTUP:
        commHandle=APMMemory.GetInstance.APMCommManager=(IntPtr)m.WParam; 
        //public IntPtr APMCommManager
        break;
    }
}

- Form Button Query Click //APM/Screen/DBM/UAPDBMQ0010.cs
string query = string.Format(@"select * from table where flag = 1");
APMPublic.GetInstance.SendQuery(currentHandle, 2, 10, MetaData.APP_TYPE.QUERY.ToString(), query);

//APM/APMPublicLib/Common/APMPublic.cs
- SendQuery(IntPtr handle, int queryindex, int columnCnt, string clientMessageTarget, string query)
{
    string timestam[ = string.Format("{0:D10}.{1:D3}", Convert.ToInt64(handle.ToString()), queryindex);

    IntPtr result = APMapiPublic.send((IntPtr)MetaData.APP_TYPE_QUERY, APMMemory.GetInstance.APMCommManager, jsonstring);
    return result;
}

//APM/APMPublicLib/Common/APMPublic.cs
- public static IntPtr send(IntPtr wParam, IntPtr hWnd, byte[] data)
- public static IntPtr send(IntPtr wParam, IntPtr hWnd, string data)
{
    IntPtr result = SendMessage(hWnd, WM_COPYDATA, wParam, sendData);
    return result;
}

protected override void WndProc(ref Message m)//APM/APMCommManager/APMCommManagerForm.cs
{
    switch(m.Msg)
    {
        case APMApiPublic.WM_COPYDATA:
        if(m.WParam==(IntPtr)MetaData.APP_TYPE.QUERY) brea;
    }

    SendToTail() //SendMessage Log Record!!

    byte[] jsonByte = Encoding.UTF8.GetBytes(jsonstring);
    sendQueue.Enqueue(jsonByte); //입력한다.

    if( ! ____sendWorker.IsBusy) ____sendWorker.RunWorkerAsync();
}

void ____sendWorker_DoWork(object sender, DoWorkEventArgs e)//APM/APMCommManager/APMCommManagerForm.cs
{
    byte[] jsonByte=sendQueue.Dequeue(); //꺼낸다.
    resultcode=____sendRedis.RPush("QCS", jsonByte); //통신시에는 byte단위를 사용
}

//APM/APMCommManager/APMCommManagerForm.cs
void ____sendWorker_Completed(object sender, CompletedEventArgs e)
{
    if(____sendQuquq.Count > 0)
        if(! ____sendWorker.IsBusy) ____sendWorker.RunWorkerAsync();
}




'c# 언어 > 기타' 카테고리의 다른 글

Application.Perfomance.Management(Receiving by Redis)  (0) 2022.01.14

/*
* C# - 마샬링이란(Marshalling)
* C# - 마샬링이란(Marshalling)
*/

1. 마샬링이란?

마샬링이란 한 객체의 메모리에서의 표현방식을 저장 또한 전송에 적합한 다른 데이터 형식으로 변환하는 과정입니다.
이는 데이터를 서로 다른 프로그램간에 전달할 필요가 있을 경우 사용합니다.
즉, 이는 직렬화와 유사하며 직렬화된 한 객체로, 멀리 떨어진 객체와 통신하기 위해 사용합니다.
이렇듯 복잡한 통신을 단순화하여 쉽게 데이터를 주고받을 수 있도록 해주는 것이 마샬링 입니다.

2. 프로그래밍에서의 마샬링

클라이언트가 서로 다른 프로세스, 원격지의 메서드를 호출해야한다고 가정합시다.
서버에 넘겨지는 인자, 리턴 값들을 프로그래밍 인터페이스에 맞도록 데이터를 조직화하고, 미리 정해진 다른 형식으로 변환합니다. 이것이 프로그래밍에서의 마샬링 입니다.
이는 XML로의 마샬링, Byte 스트림으로의 마샬링 등 다양한 방법이 있는데
이처럼 데이터 교환시 어떠한 정해진 표준에 맞게 해당 데이터를 가공하는 것이 마샬링이라면, 
가공된 데이터를 원격지에서 사용하기위한 과정을 언마샬링 이라고 합니다.

마살링도 참조 마샬링과 값 마샬링으로 구분할 수 있습니다.

참조 마샬링(MBR): MarshalByRefObject 를 상속
- 객체의 메모리를 통째로 저장한 후 다른 머신에서 객체를 복원해서 사용하는 기술
값 마샬링(MBV): Serializable Attribute를 지정하거나 ISerializable 인터페이스를 구현
- 참조 마샬링이란 객체를 핸들하기 위한 정보만을 묶어서 넘긴 후 그 정보를 이용해서 원격으로 객체를 핸들하는 기술

3. 결론

클라이언트에서 마샬링된 데이터를 서버나 다른 프로세스에 전달하게 되면, 
그 원격지에서는 데이터를 받아 언마샬링하여 사용함으로써 상호간의 통신하며 데이터를 사용할 수 있습니다.
이전 포스팅에서 프로세스 통신에 대해 소개한 적이 있는데, 
그 예제에서 사용했던 것이 바로 바이트 스트림으로의 마샬링 입니다.

Send    : string(Query) -> byte
Receive : byte -> string -> json(Data)

        public static void SendRedisDoWork(object sender, DoWorkEventArgs e)
        {
            string hostName = System.Environment.MachineName + "." +
               Microsoft.Win32.Registry.LocalMachine.OpenSubKey(
                   "SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters").GetValue("Domain", "").ToString();

            RedisClient rc = new RedisClient(parms.Host, parms.Port);

            for (int i = 0; i < parms.NumMessages; i++)
            {
                JObject o = new JObject
                {
                    {"Application", "redis-generator"},
                    {"Host", hostName},
                    {"UtcTimestamp", DateTime.UtcNow.ToString("o")},
                    {"Type", "redis"},
                    {"Message", "redis message " + DateTime.UtcNow.ToString("o")},
                    {"Index", "logstash"}
                };
                byte[] bytes = System.Text.Encoding.UTF8.GetBytes(o.ToString());

                int restult = rc.RPush("QCS", bytes);
            }
        }

using System;

class Program
{
public static void Main()
{
int kk;
string str = "QUERY.0123456789.001";

string[] split = str.Split('.');

for(kk=0; kk<split.Length; kk++)
{
Console.WriteLine(">>>>[" + kk.ToString("0000") + "]:" + split[0] + "/" + split[1] + "/" + split[2]);
}
}
}

/*-------------------------------------------------------
>>>>[0000]:QUERY/0123456789/001
>>>>[0001]:QUERY/0123456789/001
>>>>[0002]:QUERY/0123456789/001
-------------------------------------------------------*/


using System;

class Program
{
static void Main()
{
String str = "1234";

Console.WriteLine(">" + "1234567890");
Console.WriteLine(">" + string.Format("{0:D10}", Convert.ToInt64(str)));
}
}

/*RESULT--------------------------------------
>1234567890
>0000001234
---------------------------------------------*/

1) NetWork Application(for example, APM)
Linux Server Program - C Language
Windows Client Program - C# Language(Visual Studio)

2) Web
Linux Server - tomcat(by java beans & jsp)
Client - Web Browser(IE,Chrome)

3) StandAlone Window Application
- C# Language(Visual Studio)

4) Batch Application IN MySQL 
- C Language

5) Console Apllication In Windows
- C Language
- C# Language
- JAVA Language

6) Javascript Program In WebBrowser
- Javascript Language, Java Server Page, Java Beans
- HTML/CSS

 

TRIS MECHANISM,,,,,,,,

>>>>MAPY=10
>>>>MAPX=10
>>>>ARR=4
>>>>DESIGN[ARR,ARR]={{1,1,1,1},{1,0,0,0},{1,0,0,0},{1,0,0,0}};
>>>>TRIS[MAPY,MAPX]
>>>>xpos=1
>>>>ypos=0
>>>>score=0

 

1 1 1 1 1 0 0 0 0 1
1 1 0 0 0 0 0 0 0 1
1 1 0 0 0 0 0 0 0 1
1 1 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 1
1 1 1 1 1 1 1 1 1 1


1. TIME EVENT (?) - c# ElapsedEventHandler()
2. KEY EVENT (?) - c# ConsoleKeyInfo Structure
3. CHECK LOGIC (?) - Common Logic


000001) 


1.  swap(2,048)  -> 10,000
2.  /boot(100)   ->  2,000(첫번째 파티션으로 만듦, 체크)
3.  /(3,072)     -> 12,000
4.  /usr(8,192)  -> 70,000
5.  /usr2(90,000)-> 90,000                               -> 120,000
6.  /var(4,096)  -> 12,000
7.  /tmp(4,096)  -> 12,000
8.  /data(70,000)-> 70,000
9.  /home(2,000) ->  2,000
10. /web(나머지 부분을 할당, 체크)

000001) Telnet
sudo apt-get install telnetd xinetd -y

service telnet
{
    disable         = no
    flags           = REUSE
    socket_type     = stream
    wait            = no
    user            = root
    server          = /usr/sbin/in.telnetd
    log_on_failure  += USERID
}

sudo /etc/init.d/xinetd restart

00004)
by root
mkdir /usr2/sinfo

00005)
groupadd other
useradd -d /usr2/sinfo -g other -s /bin/bash sinfo
passwd sinfo

00006)
cd /usr2
chown -R sinfo:other sinfo

00007)
apt update -y
apt-get install vsftpd

>>vsftpd.conf 파일 수정
vi /etc/vsftpd.conf
# Uncomment this to enable any form of FTP write command.
write enable=YES

>>vsftpd 서비스 재시작
/etc/init.d/vsftpd restart

00008)

apt-get update

apt-get install make
apt-get install gcc
apt-get install g++ 
apt-get install net-tools
apt-get install curl
apt install pkg-config

apt-get install cmake
apt-get install libssl-dev
apt-get install libexpat1-dev
apt-get install libboost-all-dev
apt-get install libncurses5-dev libncursesw5-dev

1. MySQL 다운로드 (경로: /usr/local)
$ cd /usr/local
$ wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.25.tar.gz
$ tar xvfz mysql-8.0.25.tar.gz

$ cd /usr/local/src/
$ wget https://boostorg.jfrog.io/artifactory/main/release/1.73.0/source/boost_1_73_0.tar.gz
$ tar xvfz boost_1_73_0.tar.gz

2.설치
$ cd /usr/local/mysql-8.0.25
$ rm -f CMakeCache.txt
$ mkdir tmp_mysql(USER ADD DIRECTORY)
$ cd tmp_mysql(USER ADD DIRECTORY)
$ cmake \
.. \
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
-DMYSQL_DATADIR=/usr/local/mysql/data \
-DMYSQL_UNIX_ADDR=/usr/local/mysql/mysql.sock \
-DMYSQL_TCP_PORT=3306 \
-DDEFAULT_CHARSET=utf8 \
-DDEFAULT_COLLATION=utf8_general_ci \
-DSYSCONFDIR=/etc \
-DWITH_EXTRA_CHARSETS=all \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_ARCHIVE_STORAGE_ENGINE=1 \
-DWITH_BLACKHOLE_STORAGE_ENGINE=1 \
-DDOWNLOAD_BOOST=1 \
-DWITH_BOOST=/usr/local/src/boost_1_73_0
$ make
$ make install

3.MySQL DB 초기화
(1)그룹 지정

$ groupadd mysql
$ useradd -r -g mysql -s /bin/false mysql
그룹과 유저를 만들어야 한다.

-r : system account
-g : 그룹 지정
-s : user의 로그인 shell

(2) 디렉토리 생성

$ cd /usr/local/mysql
$ mkdir mysql-files
편한 이름의 디렉토리를 만들어 준다.

(3)권한주기

$ chown -R mysql:mysql /usr/local/mysql
$ chown mysql:mysql mysql-files
$ chmod 750 mysql-files
chown: 파일의 소유자를 변경

-R : 하위 디렉토리까지 소유권 할당

chmod : 사용권한을 변경

(4)기본 DB 생성

$ bin/mysqld --initialize --user=mysql \
--basedir=/usr/local/mysql \
--datadir=/usr/local/mysql/data

임시비밀번호가 나온다.
이 비밀번호는 나중에 써야하니 잘 기억해두자!
root@localhost : hYyR#f#D1ZCb

아래 명령어로 mysql로 전환한다.

$ bin/mysql -u root -p
명령어를 치면 비밀번호를 입력하게 되는데 아까 받은 초기 비밀번호를 입력하면 된다.

(2) 비밀번호 할당하기

mysql>alter user 'root'@'localhost' identified by '원하는 비밀번호';
mysql>flush privileges;
mysql>commit;

(3) 서버 종료


이때 비밀번호가 잘 변경됬는지 확인하면 된다.

5.MySQL 서비스 등록
서비스를 등록하면 서버가 실행되었을 때, mysql 이 자동으로 실행된다.

mysqld 파일을 복사한다.

$ sudo cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
mysqld 파일을 열어서 basedir 와 datadir 를 설정한다.

$ sudo vi /etc/init.d/mysqld


basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
mysqld 서비스를 등록한다.

$ update-rc.d mysqld defaults
reboot로 다시 시작한 뒤 보면 서버시작 안 해도 서버 시작이 되어있음을 확인할 수 있다.

$ reboot 
$ ps -ef | grep mysqld

/*----------------------------------------------------------*/



create database stockDB;
flush privileges;


백업)
/usr/local/mysql/bin/mysqldump -u root -p mysql > mysql_db.sql
(mysql>root계정까지 백업되므로, root패스워드가 원복시에 바뀌어버린다. 주의해야 한다.)
(mysql>root계정까지 백업되므로, root패스워드가 원복시에 바뀌어버린다. 주의해야 한다.)

원복)
/usr/local/mysql/bin/mysql -u root -p mysql < mysql_db.sql
(mysql>root계정까지 백업되므로, root패스워드가 원복시에 바뀌어버린다. 주의해야 한다.)
/usr/local/mysql/bin/mysql -u root -p stockDB < stockDB_db.sql

Install gcc downgrade)
add-apt-repository 'deb http://archive.ubuntu.com/ubuntu/ trusty main'
add-apt-repository 'deb http://archive.ubuntu.com/ubuntu/ trusty universe'
apt install gcc-4.7 g++-4.7 -y

update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.7 10

비고)
update-alternatives --config gcc
update-alternatives --config g++

Compile)

root@stock:~# gcc --version
gcc (Ubuntu/Linaro 4.7.3-12ubuntu1) 4.7.3
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

root@stock:~#

PATH설정)

sinfo@stock:~/exe$ ./Batch
./Batch: error while loading shared libraries: libmysqlclient.so.21: cannot open shared object file: No such file or directory
sinfo@stock:~/exe$
sinfo@stock:~/exe$


root@stock:/usr/local# find ./ -name libmysqlclient.so.21
./mysql/lib/libmysqlclient.so.21
root@stock:/usr/local#

즉 /usr/local/mysql/lib 디렉토리를 /etc/profile에 추가시켜주면 됩니다. 혹은 개인계정 profile에 추가해도 무방

# vi /etc/profile
export LD_LIBRARY_PATH=/usr/local/mysql/lib/:LD_LIBRARY_PATH

100_partition_user_add_info.txt
0.00MB
110_install_make_succ.txt
0.00MB

 

this.Text = "베트남어: Ti?ng Thai"; 를 이용한 

SendMessage[WM_COPYDATA] 는 실패!!

만국공통어인 영어를 사용해서 FindWindow를 실행해야 할것 같음.


using System;
using System.Windows.Forms;
using System.Text;
using System.Runtime.InteropServices;


namespace RecvPackage
{
public class Program : Form
{
public const int WM_COPYDATA=0x004A;

public struct COPYDATASTRUCT
{
public IntPtr dwData;
public int cbData;
public IntPtr lpData;
}

public Program()
{
//From FindWindow(), This Application is Detected!!
//From FindWindow(), This Application is Detected!! //The KeyWord is Below String,,,,,
this.Text = "RecvSendDataMonitoring";
}

protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
try
{
switch(m.Msg)
{
case WM_COPYDATA :
COPYDATASTRUCT cds = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));
byte[] recvData = new byte[cds.cbData];
Marshal.Copy(cds.lpData, recvData, 0, cds.cbData);
Console.WriteLine(Encoding.Default.GetString(recvData));

break;
}
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}

public static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Program());
}
}//end of class
}//end of namespace

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WinTrisEx01
{
public partial class Form1 : Form
{
public const int WM_COPYDATA = 0x004A;

int xpos=0;

[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("User32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

IntPtr tailHandle = IntPtr.Zero;

public struct COPYDATASTRUCT
{
public IntPtr dwData;
public int cbData;
public IntPtr lpData;
}

public Form1()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
SendToTail(1, ">>>>SendData:[" + xpos.ToString("00000") + "]");
xpos++;
}

private void SendToTail(int index, string data)
{
tailHandle = FindWindow(null, "RecvSendDataMonitoring");
try
{
byte[] dataByte = Encoding.UTF8.GetBytes(data);

COPYDATASTRUCT copyData = new COPYDATASTRUCT();
copyData.dwData = (IntPtr)0;
copyData.cbData = data.Length;
copyData.lpData = Marshal.AllocHGlobal(dataByte.Length);
Marshal.Copy(dataByte, 0, copyData.lpData, dataByte.Length);

IntPtr sendData = Marshal.AllocHGlobal(Marshal.SizeOf(copyData));
Marshal.StructureToPtr(copyData, sendData, true);

IntPtr _result = SendMessage(tailHandle, WM_COPYDATA, (IntPtr)index, sendData);

Marshal.FreeHGlobal(copyData.lpData);
Marshal.FreeHGlobal(sendData);
}
catch (Exception exp)
{
MessageBox.Show(exp.Message);
}
}
}
}

/*
 * From BackgroundWorker 매카니즘
 */

1. 서버로 data 송신시 -> SendWorker
2. 서버에서 data 수신시 -> RecvWorker
3. Queue에 데이타 입력시 -> SendQueue
4. Queue에 데이타 출력시 -> RecvQueue
5. 출력되어진 데이타를 Grid에 Display시 -> RecvQueue

From BackgroundWorker, 업무를 처리하는 동안, 어떤 방해도 받지 않는다.

+ Recent posts