본문 바로가기

C#

[C#] TCP 화면 전송 예제

TCP 클라이언트 / 서버 샘플

이번 아티클에서는 TCP 클라이언트와 TCP 서버가 서로 통신하는 간단한 샘플을 소개. 이 샘플은 TCP 클라이언트가 화면 캡처해서 TCP 서버로 전송하는 예제. 간단한 예시를 위한 것으로 복잡한 프로토콜을 사용하지는 않았으며, 가장 단순하게 처음 전송 바이트수를 보내고 다음으로 실제 바이트들을 전송하게 됨. 또한, 가능한 한 단순하게 핵심 기능만 포커스하기 위해 에러 체킹 및 부수적인 코드 등은 생략함

 

TCP 클라이언트 예제

TCP 클라이언트는 스크린 캡처한 Bitmap 이미지를 바이트 배열로 변환하여 이를 TCP 서버 127.0.0.1:7000으로 전송하는 일을 한다. 전송을 위해 먼저 이미지의 총 바이트수를 전단하여 서버가 얼마만큼의 데이터를 받을지 알게하고, 이후 실제 이미지 바이트 데이터를 전송한다. 데이터 전송이 모두 끝난 후, TCP 서버가 결과를 리턴하면 이를 받아 전송 성공 여부를 화면에 표시한다. 전송 결과를 간단히 한 바이트로서 1이면 성공, 0이면 실패이다.

 

using System;
using System.Net.Socket;
using System.Drawing;
using System.Windows.Forms;

namespace ScrCli
{
	class Program
    {
    	static void Main(string [] args)
        {
        	int BUFF_SIZE = 1024;
            string server = "127.0.0.1";
            int prot = 7000;
            
            TcpClient tc = new TcpClient(server, port);
            
            Bitmap bmp = ScreenCapture();
            var imgconv = new ImageConverter();
            byte [] imgbytes = ( byte [] ) imgconv.ConvertTo(bmp, typeof ( byte []));
            byte [] nbytes = BitConverter.GetBytes(imgbytes.Length);
            
            using (NetworkStream stream = tc.GetStream())
            {
            	// (1) 먼저 데이터 크기 전달
                stream.Write(nbytes, 0, nbytes.Length);
                
                // (2) 다음 실제 데이터 전달
                int end = imgbytes.Length;
                int start = 0;
                while (start < end)
                {
                	int n = end - start >= BUFF_SIZE ? BUFF_SIZE : end - start;
                    stream.Write(imgbytes, start, n);
                    start += n;
                }
                
                // (3) 결과 수신 : 성공이면 1, 실패이면 0
                byte [] result = new byte [1];
                stream.Read(result, 0, result.Length);
                Console.writeLine(result[0]);
            }
            
            tc.Cloese();
        }
        
        static Bitmap ScreenCapture()
        {
        	Rectangle rect = Screen.PrimaryScreen.Bounds;
            Bitmap scrbmp = new Bitmap(rect.width, rect.Height);
            
            using (Graphics g = Graphics.FromImage(scrbmp))
            {
            	g.CopyFromScreen(rect.X, rect.Y, 0, 0, scrbmp.Size, CopyPixelOperation.SourceCopy);
            }
            return scrbmp;
        }
    }

 

TCP 서버 예제

TCP 서버는 로컬 컴퓨터의 7000 포트를 열고 스크린 이미지를 수신하는 일을 한다. (프로그램을 처음 실행하면 Firewall의 7000 포트를 허용하는 다이얼로그가 뜨게 된다) TCP 클라이언트에서 전송하는 데이터의 순서에 따라 먼저 이미지 크기를 4바이트로 전송받아 이를 int로 변환한다. 다음으로 총 이미지 바이트수 만큼 계속 루프를 돌며 데이터를 전송받은 후, 이를 파일로 저장한다. 전송이 끝난 후 성공여부를 한 바이트로 송신한다. 여기서 통신상의 에러 등을 체크하여 실패를 체크하는 부분은 생략하였다.

 

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;

namespace ScrSrv
{
	class Program
    {
    	static void Main(string [] args)
        {
        	RunServer();
            Console.ReadLine();
        }
        
        // illustration purpose only
        async static void Runserver()
        {
        	int BUFF_SIZE = 1024;
            
            TcpListener listener = new TcpListener(IPAddress.Any, 7000);
            listener.Start();
            
            while(true)
            {
            	TcpClient tc = await listener.AcceptTcpClientAsync().ConfigureAwait(false);
                NetworkStream stream = tc.GetStream();
                
                // (1) 먼저 데이터 크기 수신
                byte [] bytes = new byte[4];
                int nb = await stream.ReadAsync(bytes, 0, bytes.Length).ConfigureAwait(false);
                if (nb != 4)
                {
                	throw new ApplicationException("Invalid size");
                }
                int total = BitConverter.ToInt32(bytes, 0);
                
                // (2) 다음 실제 데이타 수신
                string filename = Guid.NewGuid().ToString("N") + ".png";
                using (var fs = new FileStream(filename, FileMode.CreateNew))
                {
                	var buff = new byte [BUFF_SIZE];
                    int received = 0;
                    while (received < total)
                    {
                    	int n = total - received >= BUFF_SIZE ? BUFF_SIZE : total - received;
                        nb = await stream.ReadAsync(buff, 0, n).ConfigureAwait(false);
                        received += nb;
                        
                        await fs.WriteAsync(buff, 0, nb);
                    }
                }
                
                // (3) 성공 여부 송신 (에러 체크 생략)
                byte [] result = new byte [1];
                result[0] = 1;	// success
                await stream.WriteAsync(result, 0, result.Length).ConfigureAwait(false);
                
                stream.Close();
                tc.Close();
            }
        }
    }

 

출처) 예제로 배우는 C# 프로그래밍