C#

TCP 화면 전송 예제

TCP 클라이언트/서버 샘플

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

TCP 클라이언트 예제

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

using System;
using System.Net.Sockets;
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 port = 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.Close();
        }

        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();
            }
        }
    }
}

본 웹사이트는 광고를 포함하고 있습니다. 광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.

Previous Next Print