반응형
원격제어 프로그램 만들기에서 구현한 이미지 송수신 부분을 라이브러리로 만들고 이를 이용하여 클라이언트와 서버 응용을 만드는 실습입니다.
ImageClient.cs
//http://ehpub.co.kr
//원격 제어 프로그램
//7. 이미지 전송 클라이언트
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace 원격제어_프로그램
{
/// <summary>
/// 이미지 전송 클라이언트
/// </summary>
public class ImageClient
{
Socket sock;
/// <summary>
/// 연결 메서드
/// </summary>
/// <param name="ip">연결할 서버 측 IP주소</param>
/// <param name="port">연결할 서버 측 Port</param>
public void Connect(string ip,int port)
{
sock = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
IPAddress ipaddr = IPAddress.Parse(ip);
IPEndPoint ep = new IPEndPoint(ipaddr, port);
sock.Connect(ep);
}
/// <summary>
/// 이미지 전송 메서드
/// </summary>
/// <param name="img">전송할 이미지</param>
/// <returns>전송 성공 여부</returns>
public bool SendImage(Image img)
{
if(sock == null)
{
return false;
}
MemoryStream ms = new MemoryStream();
img.Save(ms, ImageFormat.Jpeg);
byte[] data = ms.GetBuffer();
try
{
int trans = 0;
byte[] lbuf = BitConverter.GetBytes(data.Length);
sock.Send(lbuf);//전송할 이미지 길이를 먼저 전송
while(trans <data.Length)
{
trans += sock.Send(data, trans, data.Length - trans, SocketFlags.None);
}
sock.Close();
sock = null;
return true;
}
catch
{
return false;
}
}
/// <summary>
/// 비동기로 이미지를 전송하는 메서드
/// </summary>
/// <param name="img">전송할 이미지</param>
/// <param name="callback">이미지 전송을 완료하였을 때 처리할 콜백</param>
public void SendImageAsync(Image img, AsyncCallback callback)
{
SendImageDele dele = SendImage;
dele.BeginInvoke(img, callback, this);
}
public void Close()
{
if(sock != null)
{
sock.Close();
sock = null;
}
}
}
/// <summary>
/// 이미지를 비동기로 전송하기 위해 정의한 대리자
/// </summary>
/// <param name="img">전송할 이미지</param>
/// <returns>이미지 전송 성공 여부</returns>
public delegate bool SendImageDele(Image img);
}
ImageServerc.cs
using System;
using System.Drawing;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace 원격제어_프로그램
{
public class ImageServer
{
Socket lis_sock;
public event RecvImageEventHandler RecvedImage = null;
public ImageServer(string ip,int port)
{
lis_sock = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
IPAddress ipaddr = IPAddress.Parse(ip);
IPEndPoint ep = new IPEndPoint(ipaddr, port);
lis_sock.Bind(ep);
lis_sock.Listen(5);
lis_sock.BeginAccept(DoAccept, null);
}
void DoAccept(IAsyncResult result)
{
if(lis_sock == null)
{
return;
}
try
{
Socket dosock = lis_sock.EndAccept(result);
Recevice(dosock);
lis_sock.BeginAccept(DoAccept, null);
}
catch
{
Close();
}
}
public void Close()
{
if(lis_sock!=null)
{
lis_sock.Close();
lis_sock = null;
}
}
private void Recevice(Socket dosock)
{
byte[] lbuf = new byte[4];
dosock.Receive(lbuf);
int len = BitConverter.ToInt32(lbuf, 0);
byte[] buffer = new byte[len];
int trans = 0;
while(trans<len)
{
trans += dosock.Receive(buffer, trans, len - trans, SocketFlags.None);
}
if(RecvedImage != null)
{
IPEndPoint ep = dosock.RemoteEndPoint as IPEndPoint;
RecvImageEventArgs e = new RecvImageEventArgs(ep, ConvertBitmap(buffer));
RecvedImage(this, e);
}
}
public Bitmap ConvertBitmap(byte[] data)
{
MemoryStream ms = new MemoryStream();
ms.Write(data, 0, (int)data.Length);
Bitmap bitmap = new Bitmap(ms);
return bitmap;
}
}
}
RecvImageEventArgs.cs
using System;
using System.Drawing;
using System.Net;
namespace 원격제어_프로그램
{
/// <summary>
/// 이미지 수신 처리를 위한 대리자
/// </summary>
/// <param name="sender">이벤트 통보 개체(게시자)</param>
/// <param name="e">이벤트 처리 인자</param>
public delegate void RecvImageEventHandler(object sender, RecvImageEventArgs e);
/// <summary>
/// 이미지 수신 이벤트 인자 클래스
/// </summary>
public class RecvImageEventArgs:EventArgs
{
/// <summary>
/// IP 단말 - 가져오기
/// </summary>
public IPEndPoint IPEndPoint
{
get;
private set;
}
/// <summary>
/// IP 주소 - 가져오기
/// </summary>
public IPAddress IPAddress
{
get
{
return IPEndPoint.Address;
}
}
/// <summary>
/// IP 주소 문자열 - 가져오기
/// </summary>
public string IPAddressStr
{
get
{
return IPAddress.ToString();
}
}
/// <summary>
/// 포트 - 가져오기
/// </summary>
public int Port
{
get
{
return IPEndPoint.Port;
}
}
/// <summary>
/// 이미지 - 가져오기
/// </summary>
public Image Image
{
get;
private set;
}
/// <summary>
/// 이미지 크기 - 가져오기
/// </summary>
public Size Size
{
get
{
return Image.Size;
}
}
/// <summary>
/// 이미지 폭 - 가져오기
/// </summary>
public int Width
{
get
{
return Image.Width;
}
}
/// <summary>
/// 이미지 높이 - 가져오기
/// </summary>
public int Height
{
get
{
return Image.Height;
}
}
/// <summary>
/// 이미지 수신 이벤트 인자 클래스
/// </summary>
/// <param name="remote_iep">상대측 EndPoint</param>
/// <param name="image">이미지</param>
public RecvImageEventArgs(IPEndPoint ep, Image image)
{
IPEndPoint = ep;
Image = image;
}
/// <summary>
/// ToString 메서드
/// </summary>
/// <returns>IP주소 및 이미지 크기를 문자열로 반환</returns>
public override string ToString()
{
return string.Format("IP:{0} width:{1} Height:{2}", IPAddressStr, Width, Height);
}
}
}
이미지 서버의 Form1.cs
using System;
using System.Net;
using System.Net.Sockets;
using System.Windows.Forms;
using 원격제어_프로그램;
namespace 이미지_수신_서버
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
ImageServer ims;
int imgcnt = 0;
private void Form1_Load(object sender, EventArgs e)
{
ims = new ImageServer(DefaultIP, 10200);
ims.RecvedImage += Ims_RecvedImage;
}
private void Ims_RecvedImage(object sender, RecvImageEventArgs e)
{
imgcnt++;
e.Image.Save(string.Format("{0}.bmp", imgcnt));
lbox_fno.Items.Add(imgcnt);
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if(lbox_fno.SelectedIndex == -1)
{
return;
}
int icnt = (int)lbox_fno.SelectedItem;
pbox.ImageLocation = string.Format("{0}.bmp", icnt);
}
static string DefaultIP
{
get
{
//호스트 이름 구하기
string host_name = Dns.GetHostName();
//호스트 엔트리 구하기
IPHostEntry host_entry = Dns.GetHostEntry(host_name);
//호스트 주소 목록 반복
foreach (IPAddress ipaddr in host_entry.AddressList)
{
//주소 체계가 InterNetwork일 때
if (ipaddr.AddressFamily == AddressFamily.InterNetwork)
{
return ipaddr.ToString();//IP 주소 문자열 반환
}
}
return string.Empty;//빈 문자열 반환
}
}
}
}
화면 캡쳐 및 이미지 전송 클라이언트의 Form1.cs
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 원격제어_프로그램;
namespace 이미지_캡쳐_및_전송_클라이언트
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
string ip;
ImageClient ic;
private void Form1_Load(object sender, EventArgs e)
{
ic = new ImageClient();
tbar_x1.Maximum = tbar_x2.Maximum = Screen.PrimaryScreen.Bounds.Width;
tbox_y1.Maximum = tbary2.Maximum = Screen.PrimaryScreen.Bounds.Height;
}
private void but_setting_ip_Click(object sender, EventArgs e)
{
ip = tbox_server_ip.Text;
}
private void but_capture_send_Click(object sender, EventArgs e)
{
if(ic == null)
{
return;
}
int left = tbar_x1.Value;
int right = tbar_x2.Value;
if(left>right)
{
int temp = left;
left = right;
right = temp;
}
int top = tbox_y1.Value;
int bottom = tbary2.Value;
if(top>bottom)
{
int temp = top;
top = bottom;
bottom = temp;
}
int width = right - left;
int height = bottom - top;
if((width == 0)||(height==0))
{
return;
}
Bitmap bitmap = new Bitmap(width, height);
Graphics gr = Graphics.FromImage(bitmap);
Size size = new Size(width, height);
gr.CopyFromScreen(new Point(left, top), new Point(0, 0), size);
ic.Connect(ip, 10200);
ic.SendImage(bitmap);
ic.Close();
pbox.Image = bitmap;
}
}
}
반응형
'프로젝트 > 원격 제어 프로그램 만들기' 카테고리의 다른 글
원격 제어 프로그램 만들기 9. 화면 수신 서버 (0) | 2020.05.12 |
---|---|
원격 제어 프로그램 만들기 8. 화면 수신 이벤트 인자 클래스 구현 (0) | 2020.05.12 |
원격 제어 프로그램 만들기 7. 원격 제어 – 화면 전송 (0) | 2020.05.12 |
원격 제어 프로그램 만들기 - 6. 원격 제어 요청 수신 서버 구현 및 요청 수신 1차 테스트 (0) | 2020.05.09 |
원격 제어 프로그램 만들기 - 5. 원격 제어 요청 수신 이벤트 인자 클래스 구현 (0) | 2020.05.09 |