C# TCP/IP Image transfer - 이미지(파일) 전송 2
C# 2021. 12. 24. 15:19 |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(0, 0, 0, 0, bitmap.Size);
g.Dispose();
return bitmap;
}
}
}
|
클라이언트 코드를 작성하고 빌드한다.
※ 참고
2021.12.25 - [C#] - C# TCP/IP Image transfer - 이미지(파일) 전송 3
'C#' 카테고리의 다른 글
C# DLL - 클래스 라이브러리 (0) | 2022.01.01 |
---|---|
C# TCP/IP Image transfer - 이미지(파일) 전송 3 (3) | 2021.12.25 |
C# TCP/IP Image transfer - 이미지(파일) 전송 1 (0) | 2021.12.23 |
C# Desktop(Screen) Capture - 스크린 캡쳐 (0) | 2021.12.23 |
C# Simple Socket Programming In Console - 간단한 콘솔 소켓 통신 (0) | 2021.12.22 |