728x90
300x250
[C#](OpenCVSharp 2.4.10) - 사진 출력

 

OpenCVSharp 2.4.10과 C#을 활용하여 사진을 출력하는 방법을 소개합니다.

(Introducing how to print photos using OpenCVSharp 2.4.10 and Visual C#.)

 

Nuget으로 "OpenCVSharp-AnyCPU 2.4.10"은 설치했다고 가정하고 진행합니다.

(Assume that you have installed "OpenCVSharp-AnyCPU 2.4.10" with Nuget.)

 


1. 로고 내려받기(Download the logo)

 

예제 그림으로 OpenCV 공식사이트에서 로고를 내려받습니다.

(Download the logo from the OpenCV official site as an example.)

 

https://opencv.org

 


2. 사용자 인터페이스 설계하기(Design the User Interface)

 

pictureBoxlpl1은 'SizeMode = StretchImage'로 해줍니다.

pictureBoxlpl1은 Size를 640 x 480으로 해줍니다.

(pictureBoxlpl1 is set to 'SizeMode = StretchImage'.)

(pictureBoxlpl1 sets the Size to 640 x 480.)

 

 

Form1은 Size를 800 x 600으로 해줍니다.

(Form1 sets the size to 800 x 600.)

 

 

아래 그림은 사용자 인터페이스를 임의로 그린 것입니다.

(The figure below is an arbitrary drawing of the user interface.)

 

 

Form1의 Load를 더블클릭해서 소스코드 작성할 수 있는 상태로 만들어줍니다.

 

 


3. 소스코드(Source Code)

 

소스코드입니다.(Source code.)

 

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 OpenCvSharp;


namespace csharpImageLoad
{

    public partial class Form1 : Form
    {
        IplImage ipl;


        public Form1()
        {
            InitializeComponent();
        }


        private void Form1_Load(object sender, EventArgs e)
        {
            ipl = new IplImage("opencv-logo-1.png", LoadMode.AnyColor);
            pictureBoxIpl1.ImageIpl = ipl;
           
        }

    }

}

 

 


4. 시연(Demonstrate)

 

시연입니다.

그림의 원본은 훨씬 화려하다는 것을 알 수 있습니다.

(Demonstration.)

(Source of the picture can be seen that much glamor.)

 

 

 


5. 참고자료(Reference)

 

 

반응형
728x90
300x250
[C#](OpenCVSharp 2.4.10) - 카메라 인식

 

이번에 소개할 것은 Nuget 패키지의 "OpenCVSharp-AnyCPU"를 설치하여 카메라 인식을 소개할 것입니다.

레거시 상으로는 지원하지 않으나 현재 가장 안정화된 버전이라고 할 수 있습니다.

(This time, we will introduce camera recognition by installing "OpenCVSharp-AnyCPU" of Nuget package.)

(It's not supported legacy, but it's still the most stable version.)

 


1. 프로젝트에 라이브러리 설치하기(Install the library in your project)

 

프로젝트(P)->Nuget 패키지->"OpenCVSharp-Any"를 검색합니다.

OpenCVSharp 4 사용을 권유하는 문구가 있겠으나 무시하고 2.4를 설치하도록 합니다.

(Search for Project (P)-> Nuget Package-> "OpenCVSharp-Any".)

(Some suggest that you use OpenCVSharp 4, but ignore it and install 2.4.)

 

 

 


2. 사용자 인터페이스 설계(User Interface Design)

 

PictureBoxlpl, Timer1을 배치합니다.

(Place PictureBoxlpl, Timer1.)

 

 

pictureBoxlpl1의 Size는 640 x 480으로 해줍니다.

(The size of pictureBoxlpl1 is 640 x 480.)

 

 

timer1의 Interval은 33입니다.

timer1의 Enabled는 true입니다.

(timer1 has an Interval of 33.)

(Enabled for timer1 is true.)

 

 

 

 

 

폼 환경의 Load, FormClosing을 더블클릭해서 소스코드 작성이 가능한 상태로 해줍니다.

(Double-click Load, FormClosing in the form environment to make the source code available.)

 

 

 

 

 

다음은 Timer1에 관한 설정입니다.

Tick를 더블클릭하여 소스코드 작성이 가능한 상태가 되도록 해줍니다.

(The following are the settings for Timer1.)

(Double click Tick to make it possible to write source code.)

 

 


3. 소스코드 입력하기(Enter the source code)

 

소스코드를 타이핑 합니다.(Type the source code.)

 


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 OpenCvSharp;

namespace OpenCVSharp_VideoCapture
{
    public partial class Form1 : Form
    {
        CvCapture capture;                        // OpenCVSharp 4부터 미지원
        IplImage src;                                 // OpenCVSharp 4부터 미지원

        public Form1()
        {
            InitializeComponent();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            src = capture.QueryFrame();
            pictureBoxIpl1.ImageIpl = src;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                capture = CvCapture.FromCamera(CaptureDevice.DShow, 0);

                /// Tip : 카메라를 2개 이상 이용한다면 0이 아닌 1로 입력하면 외부 카메라로 인식되어 출력됩니다.

                /// Tip : 동영상 파일 사용시 CvCapture.FromFile("경로")를 사용하여 동영상을 재생시킬 수 있습니다.
                capture.SetCaptureProperty(CaptureProperty.FrameWidth, 640);
                capture.SetCaptureProperty(CaptureProperty.FrameHeight, 480);
            }
            catch
            {
                timer1.Enabled = false;
            }

        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            Cv.ReleaseImage(src);
            if (src != null)
                src.Dispose();
        }

    }

}

 


4. 시연(Demonstrate)

 

아래의 그림은 동영상 재생을 시연한 것입니다. 모자이크 처리하였습니다.

 

 

반응형
728x90
300x250
[C#](OpenCVSharp 4) - Face Detection(얼굴 인식)

 

Face Detection(얼굴 인식)을 C# GUI환경에서 구현하는 방법에 대해 소개하려고 합니다.

OpenCV 공식 github사이트에서 라이브러리를 내려받은 후 진행할 것입니다.

(Let me introduce how to implement Face Detection in C# GUI environment.We will proceed after downloading the library from the official OpenCV github site.)

 

 


1. OpenCV 프로젝트 내려받기

 

http://github.com/opencv/opencv

http://github.com/opencv/opencv/data

 

 

 

 

이 파일이 얼굴 인식에 사용되는 중요한 라이브러리입니다.

(This file is an important library for face recognition.)

얼굴 인식 기능을 사용하려면, 프로젝트에 포함시켜야 합니다.
(To use face detection, you must include it in your project.)

 

[첨부(Attachment)]

haarcascade_frontalface_alt.7z

 

 


2. Nuget으로 OpenCVSharp 4 설치하기(Installing OpenCVSharp 4 with Nuget)

 

프로젝트->Nuget 패키지 관리를 클릭합니다.

"OpenCvSharp4"를 검색하여 설치하도록 합니다.
(Click Project-> Nuget Package Management.Search for "OpenCvSharp4" and install it.)

 

 

 


3. 사용자 인터페이스 구성(Configure the User Interface)


OpenCvSharp.UserInterface 내에 있는 PictureBoxlpl 하나, Timer 하나를 배치합니다.

 

Form1은 Load 코드를 활성화합니다.

Timer1은 Enabled = true로 해주고, Interval은 33으로 해줍니다.

Timer1의 Tick를 활성화해줍니다.

(Form1 activates the Load code.)

(Timer1 sets Enabled = true and Interval sets 33.)

(Activate Tick of Timer1.)

 


4. 프로젝트 내에 중요한 설정하기(Make important settings within your project)

 

세 가지 사항을 별표로 하였습니다.(Three points are starred.)

 

 

 

 

 

 

 

haarcascade_frontalface_alt.xml, opencvSharpExtern.dll은 출력 디렉터리에 복사 항목을 "새 버전이면 복사"에 체크해줍니다.

OpenCVSharpExtern.dll은 아래의 사이트에서 내려받을 수 있습니다.
(haarcascade_frontalface_alt.xml, opencvSharpExtern.dll checks "Copy if newer version" to the output directory.

OpenCVSharpExtern.dll can be downloaded from the site below.)

 

https://github.com/shimat/opencvsharp/releases

 

 

 


5. 코드 작성

 

코드를 작성해봅니다.

 

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 OpenCvSharp;

namespace CsharpFaceDetection
{
    public partial class Form1 : Form
    {

        VideoCapture video;
        Mat frame = new Mat();

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

            try
            {
                video = new VideoCapture(0);
                video.FrameWidth = 640;
                video.FrameHeight = 480;
            }
            catch
            {
                timer1.Enabled = false;
            }

        }

        private void timer1_Tick(object sender, EventArgs e)
        {

            int sleepTime = (int)Math.Round(1000 / video.Fps);

            String filenameFaceCascade = "haarcascade_frontalface_alt.xml";
            CascadeClassifier faceCascade = new CascadeClassifier();

            if (!faceCascade.Load(filenameFaceCascade))
            {
                Console.WriteLine("error");
                return;
            }

            video.Read(frame);

            // detect
            Rect[] faces = faceCascade.DetectMultiScale(frame);
            Console.WriteLine(faces.Length);

            foreach (var item in faces)
            {
                Cv2.Rectangle(frame, item, Scalar.Red); // add rectangle to the image
                Console.WriteLine("faces : " + item);
            }

            // display
            pictureBoxIpl1.ImageIpl = frame;

            Cv2.WaitKey(sleepTime);
        }
    }
}

 

[첨부(Attachment)]

Form1.7z

 


6. 시연하기(Demonstrate)

 

 


7. 참고자료(Reference)

 

1. [C#](OpenCVSharp 4) - c#에서 OpenCV 카메라 열기와 처음 시작하기, Last Modified 2019-11-10, Accessed by 2019-11-11, https://yyman.tistory.com/1350?category=809859

2. opencv/haarcascade_frontalface_alt.xml at master · opencv/opencv , Last Modified , Accessed by 2019-11-11,

https://github.com/opencv/opencv/blob/master/data/haarcascades/haarcascade_frontalface_alt.xml

3. opencv/opencv: Open Source Computer Vision Library, Last Modified, Accessed by 2019-11-11,

https://github.com/opencv/opencv

4. Releases · shimat/opencvsharp, Last Modified 2019-11-10, Accessed by 2019-11-11, https://github.com/shimat/opencvsharp/releases

반응형
728x90
300x250
[C#](OpenCVSharp 4) - Image 출력하기
 

Microsoft C# OpenCVSharp 4로 그림을 출력하는 방법에 대해서 간단하게 소개하겠습니다.
(Here's a quick introduction to how to print a picture with Microsoft C # OpenCVSharp 4.)

 


1. 사용자 인터페이스 설계(User Interface Design)

 

아래의 그림은 사용자 인터페이스를 설계한 것입니다. 콘솔환경이 아니라 윈도우 환경에서 시연하였습니다.
(The figure below shows the design of the user interface. It was demonstrated in the Windows environment, not the console environment.)

 

 


2. 폼 Load 기능 설계(Form Load Function Design)

 

폼 기능 설계입니다. 솔루션 탐색기 아래에 Form1로 선택하시고 번개표시를 클릭하면 아래의 그림을 볼 수 있습니다.

Load의 빈 칸을 더블클릭하면 코드를 생성할 수 있습니다.
(Form feature design.
Select Form1 under Solution Explorer and click the lightning bolt to see the figure below.You can generate code by double clicking on the blank of Load.)

 

 


3. 코드 작성(Write the code)

 

코드를 입력하면 됩니다.(Just enter the code.)

 

 

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 OpenCvSharp;


namespace OpenCVSharpImage
{
    public partial class Form1 : Form
    {

        Mat image;


        public Form1()
        {
            InitializeComponent();
        }


        private void Form1_Load(object sender, EventArgs e)
        {

            image = Cv2.ImRead("cat.jpg", ImreadModes.Grayscale);
            // Cv2.ImShow("image", image);
            // Cv2.WaitKey(0);
            // Cv2.DestroyAllWindows();

            pictureBoxIpl1.ImageIpl = image;


        }

    }

}

 

첨부(Attachment)

191110 - cat.7z // 사진 파일


4. 완성(complete)

 

그레이 형태로 완성이 되었습니다.

 

완성된 모습입니다.(It's finished.)

 


5. 영상으로 시연된 모습 구경하기(Watch the video demonstration)

 

OpenCVSharp 4 그림 출력에 대해서 시연하였습니다.
(Demonstration of OpenCVSharp 4 figure output.)

 

 

 

반응형
728x90
300x250

[C#](OpenCVSharp 4) - c#에서 OpenCV 카메라 열기와 처음 시작하기

 

안녕하세요. C#에서 OpenCV를 활용할 수 있는 방법에 대해서 소개하려고 합니다.

 

 

프로젝트->NuGet 패키지 관리를 클릭하면 위의 그림을 살펴볼 수 있습니다.

OpenCVSharp4라고 검색한 후 설치하면 됩니다. 

 

 


2. 몇 가지 흥미로운 문제

 

소스코드는 다음과 같습니다.

 

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 OpenCvSharp;


namespace OpenCV_Sample
{

    public partial class Form1 : Form
    {
        VideoCapture video;
        Mat frame = new Mat();

  
        public Form1()
        {
            InitializeComponent();
        }

 

}

 

정상적인 경우라면, 자연스럽게 빈화면을 출력해야 합니다.

그러나 아래처럼 오류가 발생합니다.

 

"내부 예외 2개 중 2개"
...... DllNotFoundException: DLL 'OpencvSharpExtern'을(를) 로드할 수 없습니다. 지정된 모듈을 찾을 수 없습니다.

 

 

 

 

 

아래의 사이트에서 프로젝트를 다운받습니다.

https://github.com/shimat/opencvsharp/releases

 

 

CPU 기종과 운영체제 기종에 맞춰서 다운받길 바랍니다.

64bit 운영체제와 64비트 CPU를 사용하고 있어서 OpenCVSharp-4.1.1-x64-20191023.zip을 내려받습니다.

 

[첨부(Attachment)]

OpenCVSharp4-master64bit.z01

OpenCVSharp4-master64bit.z02

OpenCVSharp4-master64bit.zip

 

 

압축해제한 폴더에서 "OpenCvSharpExtern.dll"을 복사합니다. 용량이 꽤 됩니다. 59,527KB(약 60Mb) 정도 됩니다.

작업중인 프로젝트 폴더에 복사해서 붙여넣어줍니다.

 

경로 찾는 방법
C:\사용자\{사용자명}\source\repos\{프로젝트명}\{프로젝트명}

 

 

다음의 단계를 그림에 맞춰서 진행해줍니다.

 

 

 

 

 

OpenCvSharpExtern.dll을 선택합니다.

 

 

그리고 우측 솔루션 탐색기에서 OpenCVSharpExtern.dll을 클릭 후 속성을 바꿔줍니다.

"출력 디렉터리에 복사"에 "항상 복사"로 바꿔줍니다.

 


2-1. dll 기종(예: 64bit이다. 또는 32bit이다.)에 맞춰주기

 

지금의 작업은 OpenCV의 기종에 맞춰서 빌드 환경을 바꿔줄 것입니다.

"Any CPU"를 클릭 후 "구성관리자"를 클릭합니다.

 

 

플랫폼에서 "Any CPU"를 클릭 후 "<새로 만들기...>"을 클릭합니다.

 

 

x64로 변경하고 확인을 클릭합니다.

 

 

변경이 된 것을 확인할 수 있습니다.

 

 


3. 사용자 인터페이스(User Interface)

 

PictureBoxlpl을 배치하고, Timer를 배치합니다.

 

 

 

 


4. 소스코드(Source Code)

 

소스코드는 아래와 같습니다.

 

namespace OpenCV_Sample
{
    public partial class Form1 : Form
    {
        VideoCapture video;
        Mat frame = new Mat();

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                video = new VideoCapture(0);
                video.FrameWidth = 640;
                video.FrameHeight = 480;
            }
            catch
            {
                timer1.Enabled = false;
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            video.Read(frame);
            pictureBoxIpl1.ImageIpl = frame;
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            frame.Dispose();
        }

    }

}

 

카메라를 시연하도록 하겠습니다. 얼굴은 모자이크 하였습니다.

 

 

 

[첨부(Attachment)]

OpenCV-Sample.z01

OpenCV-Sample.z02

OpenCV-Sample.z03

OpenCV-Sample.zip

 

 

반응형
728x90
300x250

[C#.NET] A 폼 닫고 B 폼 열기

Visual Basic 6을 사용해보신 분은 'hide'와 'show'만 가지고 자유자재로 컨트롤을 쉽게 제어할 수 있었습니다.
더불어 Application의 닫기 이벤트 또한 내부함수로 구성되어 있어서 사용하기에 편리했습니다.
C#은 문제를 도출하기 위해 다소 다른 방법을 사용합니다.
이 예제는 그러한 상황을 해결하기 위해 만들어졌습니다.


1. 인터페이스 설계

'Sample'이라는 제목을 가지고 있는 A 폼 입니다.
'Main'이라는 제목을 가지고 있는 B 폼 입니다.

 

 

 

 

 

 

 

그림 1) A 폼 닫고 B 폼 열기

솔루션 탐색기에서 'Program.cs'를 클릭합니다.


2. 구현

아래의 글 상자는 초기 소스 코드입니다.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace sample
{
    static class Program
    {
        /// <summary>
        /// 해당 응용 프로그램의 주 진입점입니다.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Login());
        }
    }
}

아래와 같이 신규 선언을 해줍니다.

            Application.Run(new Login());
            Main MainApp = new Main();
            Application.Run(MainApp);


Main은 이 예제의 실제 파일 이름입니다.
Application.Run()은 메인 폼 호출에서 도출해낸 아이디어입니다.



A폼으로 소스(Login.Designer.cs)를 엽니다.
초기 소스는 아래와 같이 선언되어 있음을 알수 있습니다.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace sample
{
    public partial class Login : Form
    {
        public Login()
        {
            InitializeComponent();
        }
    }
}


폼을 아래와 같이 구성 합니다.



그리고 버튼을 더블 클릭합니다.

        private void sLogin_Btn_Click(object sender, EventArgs e)
        {
        }


위와 같은 소스가 추가 됨을 알 수가 있습니다.

        {
        }


사이에 소스 코드를 입력합니다.

            Main MainApp = new Main();
            MainApp.Show();

            this.Close();



그리고 B 폼을 신규 윈도우 폼 추가합니다. 폼 이름은 Main으로 설정합니다.

조금 여운을 남겨놓습니다.
Program.cs에 클래스를 활용한다면 A 폼을 종료할 때 B 폼이 강제적으로 실행되는 것을 막을 수 있습니다.

반응형
728x90
300x250

[네트워크(Networks)] C#, C++, Java에서의 소켓 프로그래밍

이번에 소개할 것은 C#, C++, Java에서 소켓 프로그래밍을 사용하는 방법에 대해서 소개한다.


1. 소스코드

C#에서의 소켓 프로그래밍 작성 예시이다.
IPv4 환경에서 확인함.

운영체제: Microsoft Windows 10
소프트웨어: Visual Studio Community 2015

 


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;

namespace Example
{
    class ServerSide
    {
        public string data = null;

        public void listenSocket()
        {
            byte[] buf;
            Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 8088);

            server.Bind(ipEndPoint);
            server.Listen(10);

            System.Console.WriteLine("연결 요청(Connection Request)");

            // 클라이언트 연결 받음.
            Socket client = server.Accept();

            // 클라이언트의 데이터 - 보내기 / 받기
            buf = new byte[1024];
            client.Receive(buf);

            System.Console.WriteLine(Encoding.Default.GetString(buf));

        }
    }

    class ClientSide
    {
        public void listenSocket()
        {
            //IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
            //IPAddress ipAddress = ipHostInfo.AddressList[0];
            // IPEndPoint ipep = new IPEndPoint(ipAddress, 8088);

            IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8088);
            String buf;
            Byte[] data;
           
            Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            client.Connect(ipep);

            Console.WriteLine("소켓 연결(Socket connect)");

            // 데이터 자료 바이트 형으로 받아오기
            data = new byte[1024];
            client.Receive(data);

            // 형 변환 -> getString() 형으로 인코딩
            buf = Encoding.Default.GetString(data);

            Console.WriteLine(buf);

            buf = "소켓 접속 확인 됐습니다.";
            data = Encoding.Default.GetBytes(buf);

            client.Send(data);
            client.Close();

            Console.WriteLine("아무 키나 눌러주세요.");
            Console.ReadLine();

        }
    }
}
 

 NetworkSide.cs

 

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;

 namespace Example
 {
       class Program
       {
               static void Main(string[] args)
               {
                       ServerSide serverside = new ServerSide() ;
                       serverside.listenSocket();
               }
       }
 } 

Program.cs

[첨부(Attachment)]
network_csharp.7z


2. (Gpp)C++에서의 소켓 프로그래밍 작성 예시입니다. (리눅스에서만 가능)

C언어로 구현된 소켓 프로그래밍을 C++에서도 지원이 가능한 형태로 제작하였다.
IPv4 기반에 맞춰 작성함.

 

 

 

운영체제: 우분투(Ubuntu 16.04)
소프트웨어: Gpp, Gcc

 

 

/*
 *   Network.h
 */

 #include <iostream>
 #include <unistd.h>
 #include <netinet/in.h>
 #include <sys/socket.h>
 #include <sys/types.h>
 #include <arpa/inet.h>

 using namespace std;

 #ifndef SERVER_H_
 #define SERVER_H_

 // 0.
 class INetwork{
       virtual void listenSingleSocket() = 0;
 };

 // 1. 서버사이드(Server-Side)
 class Server : public INetwork{

 protected:

 private:
     int welcomeSocket, newSocket;

 public:
     Server(){
            this->welcomeSocket = 0;
            this->newSocket = 0;
     }

     void listenSingleSocket(){

           char buffer[1024];
           struct sockaddr_in serverAddr;
           struct sockaddr_storage serverStorage;
           socklen_t addr_size;

           welcomeSocket = socket(PF_INET, SOCK_STREAM, 0);

           serverAddr.sin_family = AF_INET;
           serverAddr.sin_port = htons(8000);
           serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

           int i = 0;

           while(i < sizeof(serverAddr.sin_zero) ){
                 serverAddr.sin_zero[i] = '\0';
                 i++;
           }

           bind(welcomeSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr) );

           if ( listen(welcomeSocket, 5) == 0 ){
                  cout << "Listening\n";
           }
           else
          {
                 cout << "Error\n";
          }

           addr_size = sizeof(serverStorage);
           newSocket = accept(welcomeSocket, (struct sockaddr *) &serverStorage, &addr_size);

           buffer[0] = 'H';
           buffer[1] = 'e';
           buffer[2] = 'l';
           buffer[3] = 'l';
           buffer[4] = 'o';

           send(newSocket, buffer, 13, 0);

     }

 };

 class Client : public INetwork{

 private:
         int clientSocket;
         char buffer[1024];
         struct sockaddr_in serverAddr;
         socklen_t addr_size;

 public:
         Client(){
               this->clientSocket = 0;
         }

         void listenSingleSocket(){

              clientSocket = socket(PF_INET, SOCK_STREAM, 0);

               serverAddr.sin_family = AF_INET;
               serverAddr.sin_port = htons(8000);

               serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

               int i = 0;
               while (i < sizeof(serverAddr.sin_zero)){
                      serverAddr.sin_zero[i] = '\0';
                       i++;
               }

                addr_size = sizeof(serverAddr);

                connect(clientSocket, (struct sockaddr *) &serverAddr, addr_size);

                // 문자열 전달 받음 - (unsigned) char[1024]
                recv(clientSocket, buffer, 1024, 0);
                cout << "데이터 전송 받은 문자:" << buffer << endl;
          }

};

#endif /* SERVER_H_ */

 Network.h

 #include <iostream>
 #include "Network.h"

 using namespace std;

 int main() {
        /*
        Server *server = new Server();
        server->listenSingleSocket();
        */

       Client *client = new Client();
       client->listenSingleSocket();
       return 0;
 }

 Program.cpp

[첨부(Attachment)]
Network-gpp.zip


3. 자바에서의 소켓 프로그래밍

싱글 쓰레드 타입으로 작성함. IPv4 환경에서 확인하였다.
IPv6는 확인하지 못함.

 

 

 

운영체제: Microsoft Windows 10 
소프트웨어: Eclipse Luna, JDK 1.81

 

 
 package Network;

 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.net.Socket;
 import java.net.UnknownHostException;

 public class ClientSide implements IHost{
 
        private Socket socket;
        private Host host;
 
        public ClientSide(){
            socket = null;
            host = null;
        }
 
        public Host getHost(){
            return host;
        }
 
        public void setHost(Host host){
            this.host = host;
        }
 
        public void listenSocket(){
  
            InputStream in = null;
            OutputStream out = null;
  
            BufferedReader br = null;
            BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
            PrintWriter pw = null;
  
            String myMsg = null;  // 전달 메시지
            String echo = null;  // 받은 메시지
  
            try{
                 socket = new Socket( host.getIP() , host.getPort() );
    
                 in = socket.getInputStream();
                 out = socket.getOutputStream();
   
                 pw = new PrintWriter(new OutputStreamWriter(out));
                 br = new BufferedReader(new InputStreamReader(in));
   
                while((myMsg = input.readLine()) != null){
    
                      if ( myMsg.equals("/q")){
                            break;
                      }
    
                      pw.println(myMsg);
                      pw.flush();
    
                      echo = br.readLine();
                      System.out.println( "서버사이드 받은 메시지:" + echo );
     
                }
   
                pw.close();
                br.close();
                socket.close();
   
        }
        catch(UnknownHostException e){
                System.out.println("미확인 호스트: " + host.getIP() + ":" + host.getPort() );
                System.exit(-1);
        }
        catch(IOException e){
                System.out.println("입출력 안됨.");
                System.exit(1);
        }

    }
 
}

 ClientSide.java

 
 package Network;

 interface IHost{
        void setHost(Host host);
        Host getHost();
 }

 public class Host{
 
        private String ip;
        private int port;
 
        public Host(int port){
              ip = "";
              this.port = port;
        }
 
        public Host(String ip, int port){
                this.ip = ip;
                this.port = port;
        }
 
        public String getIP(){
                return this.ip;
        }
 
        public int getPort(){
                return this.port;
        }
 
 }

 Host.java

 
 package Network;

 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.net.ServerSocket;
 import java.net.Socket;

class ClientWorker implements Runnable{

         private int id;
         private Socket client;
         private String line;
 
         public ClientWorker(Socket client, int id){

              this.client = client;
              this.id = id;
         }
 
         public void run() {
  
             InputStream in = null;
             OutputStream out = null;
  
             PrintWriter pw = null;
             BufferedReader br = null;
  
             String recvStr = "";

             try{
                 in = client.getInputStream();
                 out = client.getOutputStream();
   
                 pw = new PrintWriter(new OutputStreamWriter(out));
                 br = new BufferedReader(new InputStreamReader(in));
   
             }catch(IOException e){
                 System.out.println("읽기 실패(Read Failed)");
                 System.exit(-1);
             }

             try {
   
                  while( (recvStr = br.readLine() ) != null ){
    
                        appendText(recvStr);
                        System.out.print( "쓰레드(Thread)" + id + ":" );
                        System.out.println(line);
                        pw.println(recvStr);
                        pw.flush();
                  }
   
                  client.close();
   
             } catch (IOException e) {
                   System.out.println("읽기 실패(Read Failed");
                   System.exit(-1);
             }
  
       }
 
        // 동기화 추가
        public synchronized void appendText(String strText){
  
              if ( line == null )
              {
                   line = strText;
              }
              else{
                   line = line + strText;
              }
        }
 
 }

 public class ServerSide implements IHost{

         private ServerSocket server;
         private Socket client;
         private Host host;
         private static int clientID;
 
         public ServerSide(){
                server = null;
                client = null;
                host = null;
                clientID = 0;
         }
 
         public Host getHost(){
                return host;
          }
 
          public void setHost(Host host) {
                 this.host = host;
          }
 
          // 싱글(Single)
          public void listenSingleSocket(){

                String line;
   
                InputStream in = null;
                OutputStream out = null;
  
                PrintWriter pw = null;
                BufferedReader br = null;
  
                String recvStr = null;
  
                try{   
                      server = new ServerSocket( host.getPort() ); 
                }
                catch(IOException e){
                      System.out.println("포트 " + host.getPort() + "번은 응답하지 않습니다.");
                      System.exit(-1);
                }
  
                try{
                      client = server.accept();
                }
                catch(IOException e){
                      System.out.println("응답 실패: 포트 " + host.getPort() + "번");
                      System.exit(-1);
                }
  
                try{
                      in = client.getInputStream();
                      out = client.getOutputStream();
   
                      pw = new PrintWriter(new OutputStreamWriter(out));
                      br = new BufferedReader(new InputStreamReader(in));
   
                }catch(IOException e){
                      System.out.println("읽기 실패(Read Failed)");
                      System.exit(-1);
                }

                try {
   
                     while( (recvStr = br.readLine() ) != null ){
     
                            System.out.print( "싱글" );
                            pw.println(recvStr);
                            pw.flush();
                    }
   
                   client.close();
                   server.close();
   
              } catch (IOException e) {
                     System.out.println("읽기 실패(Read Failed");
                     System.exit(-1);
              }
  
         }

        // 멀티(Multi-Threading)
        public void listenMutliSocket(){
   
              ClientWorker w = null;

              try{
                  server = new ServerSocket( host.getPort() ); 
              }
              catch(IOException e){
                  System.out.println("포트 " + host.getPort() + "번은 응답하지 않습니다.");
                  System.exit(-1);
              }
  
              try{
                   while(true){
   
                        w = new ClientWorker( server.accept(), clientID++ );
  
                        Thread t = new Thread(w);
                        t.start();
                   }
   
             }
             catch(IOException e){
                  System.out.println("응답 실패: 포트 " + host.getPort() + "번");
                  System.exit(-1);
             }
  
       }
  
       protected void finalize(){
  
             try{
                  server.close();
             }catch(IOException e){
                  System.out.println("소켓을 종료할 수 없습니다.");
                  System.exit(-1);
             }
  
       }

 }

 ServerSide.java

 package Network;

 public class Example{
 
        public static void main(String[] args){
  
             ServerSide server = new ServerSide();
             Host host = new Host(10001);
             server.setHost(host);
             server.listenMutliSocket();
        }
 }

 Example.java

[예제 - 첨부(Attachment)]
Network.zip


4. IPv4와 IPv6

 

네트워크와 관련된 주제로 IPv4와 IPv6에 대해서 소개한다.

 4-1. IPv4 

 IPv4는 인터넷 프로토콜의 4번째 판이며, 전 세계적으로 사용된 첫 번째 인터넷 프로토콜이다.

 과거에 인터넷에서 사용되는 유일한 프로토콜이였으나 오늘날에는 IPv6이 대중화되었다. IETF RFC 791(1981년 9월)에 기술되어 있다.

 IPv4는 패킷 교환 네트워크 상에서 데이터를 교환하기 위한 프로토콜이다. 데이터가 정확하게 전달될 것을 보장하지 않고,
 중복된 패킷을 전달하거나  패킷의 순서를 잘못 전달할 가능성도 있다. 데이터의 정확하고 순차적인 전달은 그보다 상위 프로토콜인
 TCP에서(그리고 UDP에서도 일부) 보장한다.

 IPv4의 주소체계는 총 12자리이며 네 부분으로 나뉜다. 각 부분은 0~255까지 3자리의 수로 표현된다. IPv4 주소는 32비트로 구성되어 있으며,
 현재 인터넷 사용자의 증가로 인해 주소공간의 고갈에 대한 우려가 높아지고 있다. 이에 따라 대안으로 128비트 주소체계를 갖는 IPv6가 등장하였다.

 중국의 경우 주소공간 고갈을 우려하여 일부에서 독자적으로 IPv9(십진제 인터넷 주소체계)과 숫자도메인(Digital Domain Name System, DDNS)이
 결합된 개념인 IP 주소와 도메인 이름이 동일한 네트워크 체제인 All-Digital-Domain-Address (ADDA)를 사용하기도 한다.

 2011년 2월 4일부터 모든 IPv4 주소가 소진되어 IPv4의 할당이 중지되었다.

 

CLASS 구성 범위
A 클래스 xxx.xxx.xxx.xxx 1.0.0.1 ~ 126.255.255.254 61.211.123.22
B 클래스 xxx.xxx.xxx.xxx 128.0.0.1 ~ 191.255.255.254 181.123.211.33
C 클래스 xxx.xxx.xxx.xxx 192.0.0.1 ~ 223.255.255.254 221.23.222.222
D 클래스 224.0.0.0 ~ 239.255.255.255
E 클래스 240.0.0.0 ~ 254.255.255.254

 그림 4-1-1. 쿼드 점으로 구분 된 IPv4 주소 표현을 이진 값으로 분해.

 이건 조금 해결할 수는 있을 듯하다. 다만 이것도 계산이 더럽다고 볼 수 있다.
 아래는 172에 대해서 해결한 것이다.

10 |  10  |  110  | 0  

  10 = | Flag |
  128번 = 000000
  129번 = 000001

   .........
  172번 = 101100

 

 4-2. IPv6

 인터넷 프로토콜 버전 6 (IPv6)은 네트워크상의 컴퓨터에 대한 식별 및 위치 시스템을 제공하고 인터넷을 통해 트래픽을 라우팅하는
 통신 프로토콜 인 IP (인터넷 프로토콜)의 최신 버전이다.

 
IPv6는 오랫동안 예상되었던 IPv4 주소 고갈 문제를 해결하기 위해 IETF (Internet Engineering Task Force)에서 개발되었다.
 
IPv6은 IPv4를 대체하기 위한 것이다. IPv6는 1998 년 12 월에 초안 표준이되었고, 2017 년 7 월 14 일에 인터넷 표준이 되었다.

 인터넷상의 모든 장치에는 식별 및 위치 정의를 위해 고유 한 IP 주소가 할당된다.
 
1990 년대의 상용화 이후 인터넷의 급속한 성장으로 인해 IPv4 주소 공간보다 장치를 연결하는 데 훨씬 많은 주소가 필요할 것이다.

 
1998 년까지 IETF (Internet Engineering Task Force)는 후임 프로토콜을 공식화했다.
 
IPv6은 128 비트 주소를 사용하며 이론적으로 2128 개 또는 약 3.4 × 1038 개 주소를 허용한다.

 
여러 개의 범위가 특수 용도로 예약되었거나 완전히 사용되지 않도록 실제 숫자가 약간 더 작다.
 
가능한 IPv6 주소의 총 수는 32 비트 주소를 사용하고 약 43 억 개의 주소를 제공하는 IPv4의 7.9 × 1024 배이다.
 
 
이 두 프로토콜은 상호 운용성을 위해 설계되지 않았기 때문에 IPv6 로의 전환이 복잡해졌다.
 
그러나 IPv4와 IPv6 호스트 간의 통신을 허용하기 위해 몇 가지 IPv6 전환 메커니즘이 고안되었다.

 IPv6은 더 큰 주소 지정 공간 외에도 다른 기술적 이점을 제공한다.
 
특히 인터넷을 통한 경로 집계를 용이하게 하는 계층적 주소 할당 방법을 허용하므로 라우팅 테이블의 확장을 제한한다.
 
멀티 캐스트 주소 사용은 확장되고 단순화되며 서비스 제공을위한 추가 최적화를 제공한다.

 장치의 이동성, 보안 및 구성 측면이 프로토콜 설계시 고려되었다.

 IPv6 주소는 그룹이 콜론으로 구분 된 네 개의 16 진수 8 개의 그룹으로 표시된다.
 (예: 2001:0db8:0000:0042:0000:8a2e:0370:7334).이 전체 표기법을 줄이는 방법이 있다.

 

그림 4-2-1. IPv6 주소 표현을 이진 형식으로 분해

 IPv6를 사람 손으로 푼다고 하면, 매우 많은 노가다가 필요하다.
 각 옥탯에 있는 16진수를 일일이 하나 하나씩 해결해야 한다.

4-3. IPv6의 패킷헤더

 



그림 4-3-1. IPv6의 패킷해더

 IPv6의 패킷해더이다. IPv6로 데이터를 송수신하면 이런 형태로 전송이 되는 것을 관찰할 수 있다.
 리눅스에 패킷 분석 툴킷이 있는데 한번 패킷해더를 추적해봐도 좋을 것이다. 

 이 패킷해더를 관찰하는 대표적인 툴킷(Tool-kits)으로 WireShark가 있다.

  
 그림 4-3-2. WireShark 시연 예

 [IPv4 to IPv6에 관한 이야기]

 IPv6를 실제로 사용하려면 많은 조건이 필요하다.
 IPv4에서 IPv6로 변환해줄 수 있는 변환장치 등이 필요하다.
 터널링도 하나의 기법이 될 수 있다.


5. 참고자료(Reference)

 

1. IPv4, Wikipedia, https://ko.wikipedia.org/wiki/IPv4, Accessed by 2018-07-27
2. IPv6, Wikipeida, https://en.wikipedia.org/wiki/IPv6, Accessed by 2018-07-27
3. IPv6 OSPFv3 ESP Packets and Decrypting with Wireshark, https://packetpushers.net/ipv6-ospfv3-esp-packets-and-decrypting-with-wireshark/, Accessed by 2018-07-27

반응형
728x90
300x250

[ASP.NET] 난수를 이용한 랜덤 수 만들기

 

난수를 이용하여 랜덤 수를 만드는 방법에 대해서 소개합니다.

 


1. 구현

Random Rand = new Random((int)DateTime.Now.Ticks);
int Iteration = 0;

 

Iteration = Rand.Next(1, 100);
Label1.Text = Iteration.ToString();

 

Datatime.Now.Ticks(틱 시간을 구하는 명령입니다.)

Rand.Next(Min 시작 값 - Integer형, Max 최대 값 - integer형)

 

 

반응형

+ Recent posts