1. 

포트 21111은 로컬 호스트(127.0.0.1)에서만 수신 대기 상태입니다. 
이는 이 포트가 현재 시스템 내의 로컬 네트워크 인터페이스에서만 접근 가능하다는 것을 의미합니다. 
외부 네트워크에서 이 포트에 접근할 수 없습니다.
root@sinfo:~# netstat -an | grep 21111
tcp        0      0 127.0.0.1:21111         0.0.0.0:*               LISTEN


2. 

포트 21111은 모든 네트워크 인터페이스(0.0.0.0)와 로컬 IPv6 주소(::1)에서 수신 대기 상태입니다. 
이는 포트 21111 가 외부 네트워크와 로컬 네트워크 모두에서 접근 가능하다는 것을 의미합니다. 
root@sinfo:~# netstat -an | grep 21111
tcp        1      0 0.0.0.0:21111           0.0.0.0:*               LISTEN
tcp6       0      0 :::21111                :::*                    LISTEN
root@sinfo:~#

1번과 2번의 소스차이는(?)

#if(false)
        private void Init()
        {
            //소켓 객체 생성 (TCP 소켓)
            listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            //엔드포인트에 소켓 바인드(Bind)
            IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 21111);
            listener.Bind(localEndPoint);

            //Listen소켓의 대기열의 길이를 설정합니다.
            listener.Listen(10);

            PublicApiNM.SendToDebug(3, "()(Init)(Listen)");

            while (true)
            {
                try
                {
                    Socket handler = listener.Accept();

                    PublicApiNM.SendToDebug(3, "()(Init)(Accept)");

                    //richTextBox1.Text = richTextBox1.Text + "Socket handler = listener.Accept() OK" + "\n";

                    Thread RealSocModel = new Thread(new ParameterizedThreadStart(SocketRunHandler));
                    RealSocModel.Start(handler);
                }
                catch (Exception ex)
                {
                    //
                }
            }
            listener.Close();
        }
#endif
#if(true)
private void Init()
{
    // IPv4와 IPv6 소켓 객체 생성 (TCP 소켓)
    ipv4Listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    ipv6Listener = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);

    // IPv4와 IPv6 엔드포인트 설정
    IPEndPoint ipv4EndPoint = new IPEndPoint(IPAddress.Any, 21111); // 모든 IPv4 주소에서 수신 대기
    IPEndPoint ipv6EndPoint = new IPEndPoint(IPAddress.IPv6Any, 21111); // 모든 IPv6 주소에서 수신 대기

    // 소켓을 엔드포인트에 바인드
    ipv4Listener.Bind(ipv4EndPoint);
    ipv6Listener.Bind(ipv6EndPoint);

    // 소켓의 대기열 길이 설정
    ipv4Listener.Listen(10);
    ipv6Listener.Listen(10);

    PublicApiNM.SendToDebug(3, "()(Init)(Listen)");

    while (!_shouldStop)
    {
try
{
    // 소켓이 닫혔는지 확인하고, 닫혔으면 루프 종료
    if (ipv4Listener.Poll(1000, SelectMode.SelectRead) && ipv4Listener.Available == 0)
    {
break;
    }

    if (ipv6Listener.Poll(1000, SelectMode.SelectRead) && ipv6Listener.Available == 0)
    {
break;
    }

    // 클라이언트 연결 수신 대기
    Socket ipv4Handler = ipv4Listener.Accept();
    Socket ipv6Handler = ipv6Listener.Accept();

    PublicApiNM.SendToDebug(3, "()(Init)(Accept)");

    // 새 스레드에서 클라이언트 처리
    Thread ipv4Thread = new Thread(new ParameterizedThreadStart(SocketRunHandler));
    ipv4Thread.Start(ipv4Handler);

    Thread ipv6Thread = new Thread(new ParameterizedThreadStart(SocketRunHandler));
    ipv6Thread.Start(ipv6Handler);
}
catch (SocketException ex)
{
    if (_shouldStop)
    {
// _shouldStop이 true일 경우, listener가 닫히면서 예외 발생할 수 있음
break;
    }

    // 그 외의 소켓 예외 처리
    PublicApiNM.SendToDebug(3, "()(Init)(Exception):" + ex.Message);
}
catch (Exception ex)
{
    // 기타 예외 처리
    PublicApiNM.SendToDebug(3, "()(Init)(Exception):" + ex.Message);
}
    }

    // 소켓 닫기
    ipv4Listener.Close();
    ipv6Listener.Close();
    PublicApiNM.SendToDebug(3, "()(Init)(Stopped)");
}

public void StopInitThread()
{
    _shouldStop = true;

    // 소켓을 닫아 블로킹 호출에서 예외를 발생시키도록 함
    if (ipv4Listener != null)
    {
ipv4Listener.Close();
    }
    if (ipv6Listener != null)
    {
ipv6Listener.Close();
    }
}
#endif

 

콘솔프로그램을 작성시에 쓰레드를 발생시키고 종료를 막기위해서 반복문을 사용하는것 외에는
방법이 없는것 같았지만, 아래와 같은 방법을 쓰면 될듯함/

 

using System;
using System.Threading;

class Program
{
    // ManualResetEvent 객체 생성
    private static ManualResetEvent manualResetEvent = new ManualResetEvent(false);

    static void Main()
    {
        Console.WriteLine("Main 스레드 시작");

        // 새로운 스레드 시작
        Thread thread = new Thread(WorkerThread);
        thread.Start();

        // ManualResetEvent를 통해 메인 스레드를 대기시킴
        manualResetEvent.WaitOne();

        Console.WriteLine("Main 스레드 종료");
    }

    static void WorkerThread()
    {
        Console.WriteLine("Worker 스레드 시작");

        // 일부 작업을 수행
        Thread.Sleep(3000); // 예: 3초 동안 작업을 수행한다고 가정

        Console.WriteLine("Worker 스레드 종료");

        // 작업이 완료되면 ManualResetEvent를 설정하여 Main 스레드를 깨움
        manualResetEvent.Set();
    }
}

정보분배수신/SQLite DB저장(file)/(동기식)HttpListener Interface/
정보분배수신/SQLite DB저장(file)/(동기식)HttpListener Interface/
정보분배수신/SQLite DB저장(file)/(동기식)HttpListener Interface/

비고)
키워드를 사용하지 않고 HTTP 서버를 구현하는 방법을 보여드리겠습니다. 
이 경우, HttpListener를 사용하여 비동기 방식이 아닌 동기 방식으로 요청을 처리합니다. 
동기 방식은 코드가 요청을 처리하는 동안 다른 작업을 수행할 수 없으므로 서버의 응답 속도가 느려질 수 있습니다.


NuGet으로 Package를 설치시에, 최신버젼으로 빌드하시면 됩니다.
./packages/Newtonsoft.Json.13.0.3/lib/net45/Newtonsoft.Json.dll
./packages/Stub.Systehttp://m.Data.SQLite.Core.NetFramework.1.0.118.0/build/net45/x64/SQLite.Interop.dll
./packages/Stub.Systehttp://m.Data.SQLite.Core.NetFramework.1.0.118.0/lib/net45/System.Data.SQLite.dll

1. 전체도식을 그려본다

 


- HTTP 인터페이스를 위한 8080포트 Listen
xterm@DESKTOP-VVAIF4D MINGW64 ~/Downloads/tmp/exture_3_0_ticker/mdiwebrowser

$ netstat -an | grep 8080
  TCP    0.0.0.0:8080           0.0.0.0:0              LISTENING
  TCP    [::]:8080              [::]:0                 LISTENING
  TCP    [::1]:8080             [::1]:50463            CLOSE_WAIT
  TCP    [::1]:8080             [::1]:50493            ESTABLISHED
  TCP    [::1]:8080             [::1]:50496            ESTABLISHED
  TCP    [::1]:50463            [::1]:8080             FIN_WAIT_2
  TCP    [::1]:50493            [::1]:8080             ESTABLISHED
  TCP    [::1]:50496            [::1]:8080             ESTABLISHED

- 정보분배 TCP데이타를 받기위한 21111포트 Listen
xterm@DESKTOP-VVAIF4D MINGW64 ~/Downloads/tmp/exture_3_0_ticker/mdiwebrowser
$ netstat -an | grep 2111
  TCP    127.0.0.1:21111        0.0.0.0:0              LISTENING


2. 거래소정보분배 TCP데이타 수신및 저장(SQLite)

3. SQLite Browser에서 나타내봅니다.(상용)

3. 거래소정보분배 TCP데이타 인터페이스(HTTP통신) - 동기식(한번에 하나의 resquest를 처리한다.)

3.1 - Text 표시
3.2 - Json 표시

SQLite를 활용한 TCP정보분배 데이타 수신및 저장

> SQLite를 활용한 TCP정보분배 데이타 수신및 저장

 

> 위의 프로그램에서 생성되어진 데이타베이스 파일을 상용SQLite DB Browser에서 열기(서로 파일이 호환됨)

SQLite는 MySQL나 PostgreSQL와 같은 데이터베이스 관리 시스템이지만, 서버가 아니라 응용 프로그램에 넣어 사용하는 비교적 가벼운 데이터베이스이다. 
일반적인 RDBMS에 비해 대규모 작업에는 적합하지 않지만, 중소 규모라면 속도에 손색이 없다. 또 API는 단순히 라이브러리를 호출하는 것만 있으며, 데이터를 저장하는 데 하나의 파일만을 사용하는 것이 특징이다. 버전 3.3.8에서는 풀텍스트 검색 기능을 가진 FTS1 모듈이 지원된다. 컬럼을 삭제하거나 변경하는 것 등이 제한된다.
구글 안드로이드 운영 체제에 기본 탑재된 데이터베이스이기도 하다.

RDBMS( oracle, mssql, sysbase, mysql, mariadb 등)와 동일하게 ansi sql을 사용할 수 있다.
다른 RDBMS와의 가장 큰 차이점은 아래와 같다.
데이터베이스별로 파일1개로 구성된다.
로컬에 파일로 저장하므로 원격접속이 안된다. 
( 웹서버와 DB서버를 별도로 구성 X, 다른 대안은 찾아보면 있다. 다른아이피의 PC를 마운트 해서 사용한다던가..등)
접속아이디나 패스워드가 없다.
다중 접속이 많아질 경우 예기치 않은 문제가 발생할 수 있다.
구글 안드로이드 운영 체제에 기본 탑재되어 있어 앱을 만들어본 경험이 있다면, 누구나 한번쯤은 사용해보고 들어봤을 것이다.
윈도우PC에서도 설치하여 사용할 수 있으며, 간단한 웹페이지를 구현할때도 별도의 설치과정이 없이 실행파일만 있으면 바로 사용할 수 있다.


1. SQLite 다운로드
http://www.sqlite.org/download.html 에 접속하여 sqllite-tools-win32-3340000.zip 파일을 다운로드 받는다.

2. 압축해제 후 sqlite3.exe 실행
적당한 곳(ex. C:\SQLite)에 압축을 푼 다음 sqlite.exe파일을 실행한다.
간혹 아래와 같이 Windows의 PC 보호라고 알림 창이 뜰 경우 "추가 정보"를 클릭 후 나타나는 "실행" 버튼을 클릭하면 된다.

3. sqlite 명령프롬프트
실행하면 윈도우 명령 프롬프트가 실행되면서 sqlite 상태로 들어간다.

5. 데이터베이스 생성
실행했으니 데이터베이스를 하나 만들고 테이블도 하나 만들어서 값을 입력하고 결과를 조회해보자

데이터베이스를 만드는 법은 2가지가 있는데, 명령 프롬프트에서 sqlite3를 실행하면서 만드는 방법과 sqlite3 안에 들어가서 만드는 방법이 있다.
방법1. sqlite3 실행과 동시에 만들기

6. 생성된 데이터베이스에 테이블 만들기
일반적인 DDL 문법으로 TEST_TABLE 이라는 테이블을 만들고 .table 명령으로 테이블 목록을 조회

7. 생성된 테이블에 데이터 넣고 조회 해보기

8. GUI 툴을 사용하여 편하게 입력한다.
  sqlitebrowser.org/dl/


개인작업내용)
SQLite를 사용하여 C#에서 테이블을 생성하고 데이터를 입력 및 조회하는 예제를 아래에 제공하겠습니다. 이 예제에서는 System.Data.SQLite를 사용합니다.

먼저, NuGet 패키지 관리자를 통해 System.Data.SQLite 패키지를 설치해야 합니다.
먼저, NuGet 패키지 관리자를 통해 System.Data.SQLite 패키지를 설치해야 합니다.

BUILD & ALL
$ find ./ -name "*Interop*.dll"
./frm/WinFrmTicker/packages/Microsoft.Office.Interop.Excel.15.0.4795.1001/lib/net20/Microsoft.Office.Interop.Excel.dll
./frm/WinFrmTicker/packages/Microsoft.Office.Interop.Excel.15.0.4795.1001/lib/netstandard2.0/Microsoft.Office.Interop.Excel.dll
./frm/WinFrmTicker/packages/MSOffice.Interop.16.0.55555/lib/Microsoft.Office.Interop.Access.Dao.dll
./frm/WinFrmTicker/packages/MSOffice.Interop.16.0.55555/lib/Microsoft.Office.Interop.Access.dll
./frm/WinFrmTicker/packages/MSOffice.Interop.16.0.55555/lib/Microsoft.Office.Interop.Excel.dll
./frm/WinFrmTicker/packages/MSOffice.Interop.16.0.55555/lib/Microsoft.Office.Interop.Visio.WorkflowAuthoring.dll
./frm/WinFrmTicker/WinFrmTicker/bin/Debug/Microsoft.Office.Interop.Visio.WorkflowAuthoring.dll
./frm/WinFrmTicker/WinFrmTicker/bin/Release/Microsoft.Office.Interop.Visio.WorkflowAuthoring.dll
./mdifrm/packages/Stub.Systehttp://m.Data.SQLite.Core.NetFramework.1.0.118.0/build/net20/x64/SQLite.Interop.dll
./mdifrm/packages/Stub.Systehttp://m.Data.SQLite.Core.NetFramework.1.0.118.0/build/net20/x86/SQLite.Interop.dll

dotnet40에서, 64비트)
dotnet40에서, 64비트)

./mdifrm/packages/Stub.Systehttp://m.Data.SQLite.Core.NetFramework.1.0.118.0/build/net40/x64/SQLite.Interop.dll

./mdifrm/packages/Stub.Systehttp://m.Data.SQLite.Core.NetFramework.1.0.118.0/build/net40/x86/SQLite.Interop.dll

dotnet45에서 , 64비트)
dotnet45에서 , 64비트)

./mdifrm/packages/Stub.Systehttp://m.Data.SQLite.Core.NetFramework.1.0.118.0/build/net45/x64/SQLite.Interop.dll



./mdifrm/packages/Stub.Systehttp://m.Data.SQLite.Core.NetFramework.1.0.118.0/build/net45/x86/SQLite.Interop.dll
./mdifrm/packages/Stub.Systehttp://m.Data.SQLite.Core.NetFramework.1.0.118.0/build/net451/x64/SQLite.Interop.dll
./mdifrm/packages/Stub.Systehttp://m.Data.SQLite.Core.NetFramework.1.0.118.0/build/net451/x86/SQLite.Interop.dll
./mdifrm/packages/Stub.Systehttp://m.Data.SQLite.Core.NetFramework.1.0.118.0/build/net46/x64/SQLite.Interop.dll
./mdifrm/packages/Stub.Systehttp://m.Data.SQLite.Core.NetFramework.1.0.118.0/build/net46/x86/SQLite.Interop.dll
./mdifrm/WINCalcMdi/bin/Release/x64/SQLite.Interop.dll
./mdifrm/WINCalcMdi/bin/Release/x86/SQLite.Interop.dll



1. SQLite 데이터베이스 및 테이블 생성

using System;
using Systehttp://m.Data.SQLite;

class Program
{
    static void Main()
    {
        string connectionString = "Data Source=sample.db;Version=3;";

        using (SQLiteConnection connection = new SQLiteConnection(connectionString))
        {
            connection.Open();

            string createTableQuery = @"
                CREATE TABLE IF NOT EXISTS users (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    name TEXT NOT NULL,
                    age INTEGER NOT NULL
                )";

            using (SQLiteCommand command = new SQLiteCommand(createTableQuery, connection))
            {
                command.ExecuteNonQuery();
            }

            connection.Close();
        }

        Console.WriteLine("Table created successfully.");
    }
}

2. 데이터 입력

using System;
using Systehttp://m.Data.SQLite;

class Program
{
    static void Main()
    {
        string connectionString = "Data Source=sample.db;Version=3;";

        using (SQLiteConnection connection = new SQLiteConnection(connectionString))
        {
            connection.Open();

            string insertQuery = "INSERT INTO users (name, age) VALUES (@name, @age)";

            using (SQLiteCommand command = new SQLiteCommand(insertQuery, connection))
            {
                command.Parameters.AddWithValue("@name", "Alice");
                command.Parameters.AddWithValue("@age", 30);
                command.ExecuteNonQuery();
            }

            connection.Close();
        }

        Console.WriteLine("Data inserted successfully.");
    }
}

3. 데이터 조회

using System;
using Systehttp://m.Data.SQLite;

class Program
{
    static void Main()
    {
        string connectionString = "Data Source=sample.db;Version=3;";

        using (SQLiteConnection connection = new SQLiteConnection(connectionString))
        {
            connection.Open();

            string selectQuery = "SELECT * FROM users";

            using (SQLiteCommand command = new SQLiteCommand(selectQuery, connection))
            {
                using (SQLiteDataReader reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        Console.WriteLine("ID: " + reader["id"]);
                        Console.WriteLine("Name: " + reader["name"]);
                        Console.WriteLine("Age: " + reader["age"]);
                        Console.WriteLine();
                    }
                }
            }

            connection.Close();
        }
    }
}

전체 코드 예제

using System;
using Systehttp://m.Data.SQLite;

class Program
{
    static void Main()
    {
        string connectionString = "Data Source=sample.db;Version=3;";

        // 테이블 생성
        using (SQLiteConnection connection = new SQLiteConnection(connectionString))
        {
            connection.Open();

            string createTableQuery = @"
                CREATE TABLE IF NOT EXISTS users (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    name TEXT NOT NULL,
                    age INTEGER NOT NULL
                )";

            using (SQLiteCommand command = new SQLiteCommand(createTableQuery, connection))
            {
                command.ExecuteNonQuery();
            }

            connection.Close();
        }

        Console.WriteLine("Table created successfully.");

        // 데이터 입력
        using (SQLiteConnection connection = new SQLiteConnection(connectionString))
        {
            connection.Open();

            string insertQuery = "INSERT INTO users (name, age) VALUES (@name, @age)";

            using (SQLiteCommand command = new SQLiteCommand(insertQuery, connection))
            {
                command.Parameters.AddWithValue("@name", "Alice");
                command.Parameters.AddWithValue("@age", 30);
                command.ExecuteNonQuery();
            }

            connection.Close();
        }

        Console.WriteLine("Data inserted successfully.");

        // 데이터 조회
        using (SQLiteConnection connection = new SQLiteConnection(connectionString))
        {
            connection.Open();

            string selectQuery = "SELECT * FROM users";

            using (SQLiteCommand command = new SQLiteCommand(selectQuery, connection))
            {
                using (SQLiteDataReader reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        Console.WriteLine("ID: " + reader["id"]);
                        Console.WriteLine("Name: " + reader["name"]);
                        Console.WriteLine("Age: " + reader["age"]);
                        Console.WriteLine();
                    }
                }
            }

            connection.Close();
        }
    }
}

이 코드는 SQLite 데이터베이스를 생성하고, 테이블을 생성한 후, 데이터를 입력하고 조회하는 예제입니다. SQLite 데이터베이스 파일(sample.db)이 실행 디렉토리에 생성됩니다.


(정보분배)TCP로 받은 증권데이타를 파싱해서 DataGridView에 표시해봅니다.



1. SDI 방식
2. MDI 방식

1. 데이타의 정합성체크(소수점등)에 활용될수 있다.
2. *.db 파일에 저장되므로, 메모리의 크기에 대한 걱정을 안해도 된다.(무한정 데이타룰 수신가능)


접속표준서(정보분배-UDP_TCP실시간)에 정의되어진 콤마가 있는항목을 따로 표시해 봅니다.
누적거래량은 콤마3으로 표시되어지므로, ".000" 부분을 잘라서 사용해야 합니다.
"."까지 포함되어졌으므로, 4자리를 잘라서 사용해야 할것 같습니다.(주의할점)

 

TCP로 받은 호가데이타를 파싱해서 DataGridView에 표시해봅니다.

통합본)

public class PublicNM
{

     public const int WM_KEYDOWN = 0x0100;

    // FindWindow를 정적 메서드로 선언합니다.
    public static IntPtr FindWindow(string lpClassName, string lpWindowName)
    {
        // 실제 FindWindow 구현은 생략
        return IntPtr.Zero; 
    }
}

사용예)

         // 정적 메서드에 접근할 때는 클래스 이름을 사용합니다.
         IntPtr hWnd = PublicNM.FindWindow("ClassName", "WindowName");

        protected override bool ProcessCmdKey(ref Message message, Keys keyData)
        {
            switch (message.Msg)
            {
                case PublicNM.WM_KEYDOWN:
                    break;
                default:
                    break;
            }
            return base.ProcessCmdKey(ref message, keyData);
        }

 

 

+ Recent posts