OpenCvSharp for Network

OpenCV 2021. 12. 28. 22:45 |
반응형

C#에서 OpenCV Mat 데이터를 네트워크로 송수신 할 수 있도록 준비하는 과정을 시뮬레이션 해 보자.

아래 링크의 글에서 비트맵이 아닌 OpenCV Mat 데이터 송수신 과정이라 보면 된다.

2021.12.25 - [C#] - C# TCP/IP Image transfer - 이미지(파일) 전송 3

 

폼에 PictureBox, Button을 적당히 배치한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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;
using System.IO;
 
namespace OpenCV
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
 
            pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            // 클라이언트 시뮬레이션
            // OpenCV Matrix를 생성하고 바이트 배열로 변환한다.
            Mat clientImage = new Mat("Barbara.jpg");
            byte[] data = clientImage.ToBytes(".jpg"); // ".jpg", ".png", ".bmp"
            //MemoryStream clientMemoryStream = clientImage.ToMemoryStream();
            //byte[] data = clientMemoryStream.ToArray();
 
            // 네트워크 시뮬레이션
            // ...
            // 클라이언트에서 OpenCV Matrix 바이트 배열(data)을 서버로 전송
 
            // 서버 시뮬레이션
            // 클라이언트에서 받은 바이트 배열(data)을 메모리 스트림으로
            // 변환 후 다시 비트맵으로 변환한다.
            MemoryStream serverMemoryStream = new MemoryStream(data);
            Bitmap bitmap = new Bitmap(serverMemoryStream);
            //Mat serverImage = OpenCvSharp.Extensions.BitmapConverter.ToMat(bitmap);
            //Cv2.ImShow("Server Image", serverImage);
            pictureBox1.Image = bitmap;
        }
    }
}
 

 

클라이언트에서 Mat.ToBytes()가 핵심이다. (메모리 스트림으로 변환할 필요가 없다)

소스를 입력하고 빌드한다.

 

실행하면 버튼만 나타난다.

 

버튼을 클릭하면 이미지가 표시된다.

 

반응형
Posted by J-sean
:
반응형

2021.12.23 - [C#] - C# TCP/IP Image transfer - 이미지(파일) 전송 1

2021.12.24 - [C#] - C# TCP/IP Image transfer - 이미지(파일) 전송 2

 

위 두 링크에서 만든 프로그램을 개선해 클라이언트의 화면을 서버로 연속 전송, 영상으로 재생해 보자.

간단한 화면공유(Screen Share) 프로그램을 만드는 것이다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
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.Threading;
using System.Net;
using System.Net.Sockets;
using System.IO;
 
namespace Server
{
    public partial class Form1 : Form
    {
        TcpListener listener;
        TcpClient client;
        NetworkStream networkStream;
        MemoryStream memoryStream;
        Bitmap bitmap;
        IPHostEntry ipHostEntry;
        Thread thread;
 
        string serverIP;
        int serverPort;
        byte[] data;
        byte[] dataSizeFromClient;
        int receivedDataSize;
        int expectedDataSize;
 
        public Form1()
        {
            InitializeComponent();
 
            pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
 
            serverPort = 7000;
            // 호스트 이름으로 검색되는 첫 번째 IP4 주소 확인
            string hostName = Dns.GetHostName();
            ipHostEntry = Dns.GetHostEntry(hostName);
            foreach (IPAddress address in ipHostEntry.AddressList)
            {
                if (address.AddressFamily == AddressFamily.InterNetwork)
                {
                    serverIP = address.ToString();
                    break;
                }
            }
            listBox1.Items.Add("Server IP: " + serverIP);
 
            data = new byte[1048576 * 10]; // 1MB * 10
                                           // 클라이언트로 부터 전송되는 PNG 파일은 상황에 따라 4MB를 넘기도 한다.
            dataSizeFromClient = new byte[sizeof(int)];
        }
 
        private void ThreadProc()
        {
            listener = new TcpListener(IPAddress.Any, serverPort);
            //listener = new TcpListener(IPAddress.Parse("127.0.0.1"), serverPort);
            listener.Start();
 
            client = listener.AcceptTcpClient();
            listBox1.Items.Add("Client IP: " + client.Client.RemoteEndPoint.ToString().Split(':')[0]);
            networkStream = client.GetStream();
 
            while (true)
            {
                try
                {
                    receivedDataSize = 0;
 
                    if (networkStream.CanRead)
                    {
                        // 클라이언트로 부터 받아야 할 데이터 사이즈 정보 확인.
                        networkStream.Read(dataSizeFromClient, 0, dataSizeFromClient.Length);
                        expectedDataSize = BitConverter.ToInt32(dataSizeFromClient, 0);
                        //listBox1.Items.Add("Expected data size: " + (expectedDataSize / 1024).ToString() + "KB");
 
                        // 데이터 수신.                        
                        do
                        {
                            // 클라이언트로 부터 받아야 할 데이터 사이즈 만큼만 정확히 받는다.
                            receivedDataSize += networkStream.Read(data, receivedDataSize, expectedDataSize - receivedDataSize);
                            // Reads data from the NetworkStream and stores it to a byte array.
                        } while (expectedDataSize != receivedDataSize);
                        //while (networkStream.DataAvailable);
                        // NetworkStream.DataAvailable 은 네트워크 상황에 따라 정확하지 않을 가능성이 크다.
                        
                        //listBox1.Items.Add("Data size: " + (receivedDataSize / 1024).ToString() + "KB");
                        // 클라이언트로 부터 받은 데이터 사이즈가 버퍼 사이즈(10MB) 보다 크다면 버퍼 사이즈를 늘려야 한다.
                        // 그렇지 않으면 NetworkStream.Read()에서 ArgumentOutOfRangeException 예외 발생.
                    }
 
                    //listBox1.Items.Add("Data received: " + (receivedDataSize / 1024).ToString() + "KB");
                    memoryStream = new MemoryStream(data, 0, receivedDataSize);
                    // Initializes a new non-resizable instance of the MemoryStream class
                    // based on the specified region (index) of a byte array.            
                    bitmap = new Bitmap(memoryStream);
                    pictureBox1.Image = bitmap;
                }
                catch (Exception e)
                {
                    listBox1.Items.Add(e.Message);
                    listBox1.Items.Add(e.StackTrace);
                    break;
                }
            }
 
            listener.Stop();
            client.Close();
            networkStream.Close();
            memoryStream.Close();
        }
 
 
        private void button1_Click(object sender, EventArgs e)
        {
            // 클라이언트 접속 대기를 위한 스레드 생성(스레드는 1개만 생성한다)
            if (thread == null || !thread.IsAlive)
            {
                thread = new Thread(new ThreadStart(ThreadProc));
                thread.Start();
                listBox1.Items.Add("Waiting for a client...");
            }
        }
 
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (thread != null && thread.IsAlive)
            {
                // TcpListener를 정지 시키지 않고 클라이언트 연결 대기시 프로그램을
                // 종료하려 하면 스레드가 종료되지 않아 프로그램이 종료되지 않는다.
                listener.Stop();
 
                // 클라이언트와 연결된 스레드를 종료하지 않으면 프로그램을 종료해도
                // 백그라운드에서 계속 실행된다.                
                thread.Abort();
            }
        }
    }
}
 

 

서버 코드를 입력하고 빌드한다.

Server.zip
0.00MB

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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.Threading;
using System.Net;
using System.Net.Sockets;
using System.IO;
 
namespace Client
{
    public partial class Form1 : Form
    {
        TcpClient client;
        NetworkStream networkStream;
        MemoryStream memoryStream;
        Bitmap screen;
        Thread thread;
 
        string serverIP;
        int serverPort;
        byte[] data;
        byte[] dataSizeForServer;
 
        public Form1()
        {
            InitializeComponent();
 
            pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
            textBox1.Text = "192.168.0.100";
        }
 
        private void ThreadProc()
        {
            serverIP = textBox1.Text;
            serverPort = 7000;
            try
            {
                client = new TcpClient(serverIP, serverPort);
                networkStream = client.GetStream();
                listBox1.Items.Add("Connected to: " + client.Client.RemoteEndPoint.ToString().Split(':')[0]);
            }
            catch (Exception e)
            {
                listBox1.Items.Add(e.Message);
                listBox1.Items.Add(e.StackTrace);
 
                return;
            }
 
            try
            {
                while (true)
                {
                    screen = GetScreen();
                    memoryStream = new MemoryStream();
                    screen.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Png);
                    data = memoryStream.ToArray();
                    pictureBox1.Image = screen;
 
                    if (networkStream.CanWrite)
                    {
                        // 보낼 데이터 사이즈를 서버에 미리 공유
                        dataSizeForServer = BitConverter.GetBytes(data.Length);
                        networkStream.Write(dataSizeForServer, 0, dataSizeForServer.Length);
 
                        // 데이터 송신
                        networkStream.Write(data, 0, data.Length);
                        //listBox1.Items.Add("Data sent: " + (data.Length / 1024).ToString() + "KB");
                    }
 
                    // Thread.Sleep()을 삭제하면 더 부드러운 화면을 볼 수 있다.
                    // 하지만 CPU 점유율이 크게 높아진다. 적절히 조정하자.
                    Thread.Sleep(100);
                }
            }
            catch (Exception e)
            {
                listBox1.Items.Add(e.Message);
                listBox1.Items.Add(e.StackTrace);
            }
 
            client.Close();
            networkStream.Close();
            memoryStream.Close();
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            // 클라이언트 접속 대기를 위한 스레드 생성(스레드는 1개만 생성한다)
            if (thread == null || !thread.IsAlive)
            {
                thread = new Thread(new ThreadStart(ThreadProc));
                thread.Start();
                listBox1.Items.Add("Connecting to the server...");
            }
        }
 
        private Bitmap GetScreen()
        {
            Bitmap bitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
            Graphics g = Graphics.FromImage(bitmap);
            g.CopyFromScreen(0000, bitmap.Size);
            g.Dispose();
 
            return bitmap;
        }
 
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (thread != null && thread.IsAlive)
            {
                // 스레드를 종료하지 않으면 백그라운드에서 계속 실행된다.
                thread.Abort();
            }
        }
    }
}
 

 

클라이언트 코드를 입력하고 빌드한다.

Client.zip
0.01MB

 

한 컴퓨터에서 서버, 클라이언트를 모두 실행한 화면

 

 

NetworkStream.DataAvailable 프로퍼티는 네트워크 상황에 따라 부정확한 경우가 많다. 그러므로 서버에서는 클라이언트로 부터 받을 데이터의 사이즈를 미리 확인하고 그 사이즈만큼 정확히 받는게 중요하다.

작은 크기의 데이터는 사이즈 정보 교환없이 한번에 송수신해도 별 문제는 없다. 하지만 이 프로그램처럼 수백 KB의 데이터를 주고 받는 경우 한번에 송수신이 되지 않을 가능성이 크다.

 

클라이언트에서는 서버로 데이터를 전송하기 전, 보낼 데이터 사이즈를 미리 공유해 서버에서 수신 준비할 수 있도록 한다.

MemoryStream으로 저장할 데이터 포맷을 ImageFormat.Jpeg로 바꾸면 ImageFormat.Png에 비해 훨씬 작은 사이즈의 데이터가 만들어지고 영상의 FPS를 향상시킬 수 있다. (PNG는 비손실 압축, JPEG는 손실 압축)

 

반응형
Posted by J-sean
:
반응형

2021.12.23 - [C#] - C# TCP/IP Image transfer - 이미지(파일) 전송 1 에서 만든 프로그램을 개선해 보자.

네트워크 접속 지연으로 발생할 수 있는 에러를 처리하고 스레드를 사용해 네트워크 접속 대기 시 freeze되는 부분을 개선했다.

 

폼 디자인은 2021.12.23 - [C#] - C# TCP/IP Image transfer - 이미지(파일) 전송 1 과 동일하다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
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.Threading;
using System.Net;
using System.Net.Sockets;
using System.IO;
 
namespace Server
{
    public partial class Form1 : Form
    {
        TcpListener listener;
        TcpClient client;
        NetworkStream networkStream;
        MemoryStream memoryStream;
        Bitmap bitmap;
        IPHostEntry ipHostEntry;
        Thread thread;
 
        string serverIP;
        int serverPort;
        byte[] data = new byte[1048576]; // 1MB
        byte[] dataSizeFromClient;
        int receivedDataSize;
        int expectedDataSize;
 
        public Form1()
        {
            InitializeComponent();
 
            pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
 
            serverPort = 7000;
            // 호스트 이름으로 검색되는 첫 번째 IP4 주소 확인
            string hostName = Dns.GetHostName();
            ipHostEntry = Dns.GetHostEntry(hostName);
            foreach (IPAddress address in ipHostEntry.AddressList)
            {
                if (address.AddressFamily == AddressFamily.InterNetwork)
                {
                    serverIP = address.ToString();
                    break;
                }
            }
            listBox1.Items.Add("Server IP: " + serverIP);
 
            listener = new TcpListener(IPAddress.Any, serverPort);
            //listener = new TcpListener(IPAddress.Parse("127.0.0.1"), serverPort);            
        }
 
        private void ThreadProc()
        {
            listener.Start();
 
            client = listener.AcceptTcpClient();
            listBox1.Items.Add("Client IP: " + client.Client.RemoteEndPoint.ToString().Split(':')[0]);
 
            networkStream = client.GetStream();
 
            receivedDataSize = 0;
            dataSizeFromClient = new byte[sizeof(int)];
 
            if (networkStream.CanRead)
            {
                // 클라이언트로 부터 받아야 할 데이터 사이즈 정보 확인.
                networkStream.Read(dataSizeFromClient, 0, dataSizeFromClient.Length);
                expectedDataSize = BitConverter.ToInt32(dataSizeFromClient, 0);
                listBox1.Items.Add("Expected data size: " + (expectedDataSize / 1024).ToString() + "KB");
 
                // 데이터 송신
                do
                {
                    receivedDataSize += networkStream.Read(data, receivedDataSize, data.Length - receivedDataSize);
                    // Reads data from the NetworkStream and stores it to a byte array.                    
                } while (networkStream.DataAvailable);
                // while (expectedDataSize > receivedDataSize);
            }
 
            listBox1.Items.Add("Data received: " + (receivedDataSize / 1024).ToString() + "KB");
            memoryStream = new MemoryStream(data, 0, receivedDataSize);
            // Initializes a new non-resizable instance of the MemoryStream class
            // based on the specified region (index) of a byte array.            
            bitmap = new Bitmap(memoryStream);
            pictureBox1.Image = bitmap;
 
            listener.Stop();
            client.Close();
            networkStream.Close();
            memoryStream.Close();
        }
 
 
        private void button1_Click(object sender, EventArgs e)
        {
            // 클라이언트 접속 대기를 위한 스레드 생성(스레드는 1개만 생성한다)
            if (thread == null || !thread.IsAlive)
            {
                thread = new Thread(new ThreadStart(ThreadProc));
                thread.Start();
                listBox1.Items.Add("Waiting for a client...");
            }
        }
 
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (thread != null && thread.IsAlive)
            {
                // 클라이언트 접속 대기 종료
                listener.Stop();
                //thread.Abort();
            }
        }
    }
}
 

 

서버 코드를 작성하고 빌드한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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.Threading;
using System.Net;
using System.Net.Sockets;
using System.IO;
 
namespace Client
{
    public partial class Form1 : Form
    {
        TcpClient client;
        NetworkStream networkStream;
        MemoryStream memoryStream;
        Bitmap screen;
        Thread thread;
 
        string serverIP;
        int serverPort;
        byte[] data;
        byte[] dataSizeForServer;
 
        public Form1()
        {
            InitializeComponent();
 
            pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
            textBox1.Text = "192.168.0.100";
        }
 
        private void ThreadProc()
        {
            screen = GetScreen();
            // pictureBox1.Image = screen;
            // 위 명령을 여기서 실행하면 아래와 같은 에러가 발생한다. (이해할 수 없다.)
            // System.InvalidOperationException: 개체를 다른 곳에서 사용하고 있습니다.
            // 서버 접속(아래 try-catch) 이후 실행하면 된다.
 
            memoryStream = new MemoryStream();
 
            screen.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Png);
            data = memoryStream.ToArray();
 
            serverIP = textBox1.Text;
            serverPort = 7000;
            try
            {
                client = new TcpClient(serverIP, serverPort);
            }
            catch (Exception e)
            {
                listBox1.Items.Add(e.Message);
                memoryStream.Close();
 
                return;
            }
 
            listBox1.Items.Add("Connected to: " + client.Client.RemoteEndPoint.ToString().Split(':')[0]);
            pictureBox1.Image = screen;
 
            networkStream = client.GetStream();
 
            if (networkStream.CanWrite)
            {
                // 보낼 데이터 사이즈를 서버에 미리 공유
                dataSizeForServer = BitConverter.GetBytes(data.Length);
                networkStream.Write(dataSizeForServer, 0, dataSizeForServer.Length);
 
                // 데이터 전송
                networkStream.Write(data, 0, data.Length);
                listBox1.Items.Add("Data sent: " + (data.Length / 1024).ToString() + "KB");
            }
 
            client.Close();
            networkStream.Close();
            memoryStream.Close();
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            // 클라이언트 접속 대기를 위한 스레드 생성(스레드는 1개만 생성한다)
            if (thread == null || !thread.IsAlive)
            {
                thread = new Thread(new ThreadStart(ThreadProc));
                thread.Start();
                listBox1.Items.Add("Connecting to the server...");
            }
        }
 
        private Bitmap GetScreen()
        {
            Bitmap bitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
            Graphics g = Graphics.FromImage(bitmap);
            g.CopyFromScreen(0000, bitmap.Size);
            g.Dispose();
 
            return bitmap;
        }
    }
}
 

 

클라이언트 코드를 작성하고 빌드한다.

 

서버 실행 후 클라이언트 접속 대기 상태에서도 freeze 되지 않는다.

 

클라이언트 실행 후 서버 접속 시도 중인 상태에서도 freeze 되지 않는다. (서버를 실행하지 않고 테스트)

 

 

서버 접속에 실패하더라도 클라이언트는 종료되지 않고 에러 메세지만 보낸다.

 

서버, 클라이언트가 문제 없이 연결되면 정상 작동한다.

 

※ 참고

2021.12.25 - [C#] - C# TCP/IP Image transfer - 이미지(파일) 전송 3

 

반응형
Posted by J-sean
:
반응형

IP 주소와 호스트 네임을 확인 해 보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
using System.Net;
 
namespace CS
{
    using static System.Console;
 
    class Program
    {
        static void Main(string[] args)
        {
            // 인터넷 url로 IP 주소 확인
            string url = "www.naver.com";
            IPHostEntry ipHostEntry = Dns.GetHostEntry(url);
            WriteLine("■ IP addresses of " + url);
            foreach (IPAddress add in ipHostEntry.AddressList)
            {
                WriteLine(add.ToString());
            }
 
            // 호스트 네임으로 IP 주소 확인
            WriteLine();
            string hostName = Dns.GetHostName();
            ipHostEntry = Dns.GetHostEntry(hostName);
            WriteLine("■ All IP addresses of " + ipHostEntry.HostName);
            // WriteLine(hostName);            
            foreach (IPAddress address in ipHostEntry.AddressList)
            {
                WriteLine(address.ToString());
            }
 
            WriteLine();
            WriteLine("■ All IP6 addresses of " + ipHostEntry.HostName);
            foreach (IPAddress address in ipHostEntry.AddressList)
            {
                if (address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)
                    WriteLine(address.ToString());
            }
 
            WriteLine();
            WriteLine("■ All IP4 addresses of " + ipHostEntry.HostName);
            foreach (IPAddress address in ipHostEntry.AddressList)
            {
                if (address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                    WriteLine(address.ToString());
            }
 
            WriteLine();
            WriteLine("■ All IP4 addresses of " + ipHostEntry.HostName);
            foreach (IPAddress address in ipHostEntry.AddressList)
            {
                if (address.ToString().Split('.').Count() == 4)
                    WriteLine(address.ToString());
            }
 
            // IP 주소로 호스트 네임 확인
            WriteLine();
            IPAddress ipAddress = IPAddress.Parse(ipHostEntry.AddressList[0].ToString());
            // IPAddress ipAddress = IPAddress.Parse("192.168.0.100"); // My internal IP address
            ipHostEntry = Dns.GetHostEntry(ipAddress);
            Console.WriteLine("■ Host name: " + ipHostEntry.HostName);
 
            // 웹사이트를 이용한 외부 IP 주소 확인
            WriteLine();
            try
            {
                string externalIP = new WebClient().DownloadString("http://ipinfo.io/ip").Trim();
                // or http://icanhazip.com
                WriteLine("■ External IP address: " + externalIP);
            }
            catch (Exception exc)
            {
                WriteLine(exc.Message);
            }
        }
    }
}
 

 

소스를 입력하고 빌드한다.

 

IP 주소 및 호스트 네임을 확인 할 수 있다.

 

반응형
Posted by J-sean
:
반응형

리눅스(우분투) 서버 IP를 고정해 보자.

 

현재 IP 주소는 192.168.171.128 이다.

 

DNS Server IP 주소는 192.168.171.2 다.

 

Gateway IP 주소는 192.168.171.2 다.

 

/etc/netplan/00-installer-config.yaml 파일을 열어준다.

 

 

00-installer-config.yaml 의 초기 설정.

 

원하는 IP 주소(192.168.171.200)와 위에서 찾은 IP 정보를 이용해 수정한다.

 

netplan apply를 실행하면 재부팅 하지 않아도 된다.

 

IP가 고정되었다.

 

반응형
Posted by J-sean
:
반응형

Raspbian을 설치하고 업데이트, 한글, 고정 IP, VNC, Samba 설정등을 진행 한다.

 

기본 사용자: pi

기본 암호: raspberry

 

sudo apt-get update

 

sudo apt-get upgrade

 

Preferences - Add/Remove Software 클릭

 

Nanum Korean fonts 설치

 

Nabi 설치

 

im-config 설치

 

 

 

Preferences - Input Method 클릭

 

OK 클릭

 

Yes 클릭

 

hangul 선택

 

OK를 클릭하고 재부팅 한다. 재부팅해도 한글 입력이 되지는 않는다.

 

Raspberry Pi Configuration - Localisation - Locale에서 언어를 한국어로 바꾸고 다시 재부팅 한다.

 

 

 

'한/영'키나 'Shift + Space'키를 누르면 한글이 입력 된다.

 

Timezone을 Asia-Seoul로 바꿔준다.

 

netstat -nr 명령어로 Gateway주소를 확인한다.

 

/etc/dhcpcd.conf 파일 아래에 고정할 ip주소를 지정한다.

 

interface eth0

static ip_address=고정할 ip주소/24

static routers=Gateway 주소

static domain_name_servers=Gateway 주소

 

(무선 랜카드를 사용 한다면 interface를 eth0이 아닌 wlan0로 바꿔 준다)

 

재부팅하고 확인해 보면 지정한 ip주소로 고정 된다.

 

Raspbian은 기본적으로 VNC Server가 설치 되어 있지만 Raspberry Pi Desktop은 VNC Server가 설치되어 있지 않다.

필요한 경우 X11VNC Server를 설치 한다.

 

 

 

X11VNC Server를 실행 한다.

 

기본 설정으로 두고 OK를 클릭 한다.

 

Accept Connections를 체크한다.

암호가 필요 없다면 그대로 두고 OK를 클릭 한다.

 

RealVNC Viewer등으로 원격 접속하여 사용 할 수 있다.

 

VNC Server를 가끔 쓴다면 위와 같이 매번 사용할 때만 실행하면 되지만 VNC Server가 항상 실행되어야 한다면 rc.local에 등록하여 부팅시 자동으로 실행 되도록 한다. /etc/rc.local 파일을 열어 준다.

 

exit 0 명령어 위에 X11VNC Server를 실행하는 명령어를 넣고 저장 한다.

 

su pi -c 'x11vnc -loop -forever'

 

아래 링크를 참고한다.

2022.05.29 - [Linux] - Linux(Ubuntu, Raspberry Pi OS) 자동실행(rc.local)

 

이제 부팅시 자동으로 X11VNC Server가 실행 된다.

 

 

 

Samba를 설치 한다.

 

/etc/samba/smb.conf 파일끝에 아래 내용을 추가 한다.

 

[share]

path = /share

public = yes

writable = yes

 

testparm 명령을 실행 해서 smb.conf 파일에 문제가 없는지 확인 한다.

 

path에 지정한 /share 디렉토리를 만들고 읽기, 쓰기, 실행이 가능하도록 rwx 권한을 준다.

 

smbd은 자동으로 실행 및 등록 된다.

 

이제 /share 디렉토리는 다른 컴퓨터에서 접근 가능 하다.

 

공유기에서 Port forwarding 설정이 필요 하다면 netstat 명령어로 필요한 port를 확인 한다.

 

컴퓨터를 켜거나 재부팅하면 항상 위와 같은 GRUB 화면이 나온다. 여기서 몇 초(5초) 기다리거나 엔터키를 한 번 눌러야 부팅이 시작된다. 바로 부팅 되도록 해보자.

 

/etc/default/grub 파일을 열자.

 

GRUB_TIMEOUT=5로 되어 있다. 그래서 5초를 기다려야 했던 것이다.

 

기다리지 않고 바로 부팅되도록 0으로 바꾸고 저장한다.

 

sudo update-grub 명령으로 업데이트 한다. 이제 기다릴 필요 없이 바로 부팅된다.

 

반응형
Posted by J-sean
: