클라이언트 연속 메시지 전송

이전 섹션의 서버 측 코드를 수정하여 클라이언트가 보내는 메시지를 지속적으로 수신할 수 있도록 하고 멀티스레딩을 활성화합니다.

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace TcpServerDemo
{
    public partial class Form1 : Form
    {
        private TcpListener listener;
        private TcpClient tcpClient;

        public Form1()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        private void btnStartServer_Click(object sender, EventArgs e)
        {
            Thread acceptThread = new Thread(() =>
            {
                IPAddress ip = IPAddress.Parse(this.textBoxIP.Text);//IP 인스턴스 생성
                listener = new TcpListener(ip, Convert.ToInt32(this.textBoxPort.Text));//TCP 리스너 객체 생성
                listener.Start();
                this.textBoxInfo.Text = "서버 시작‑" + DateTime.Now.ToShortTimeString() + "\r\n" + this.textBoxInfo.Text;
                tcpClient = listener.AcceptTcpClient();//차단 상태로 연결 대기
                this.textBoxInfo.Text = "연결 성공‑" + DateTime.Now.ToShortTimeString() + "\r\n" + this.textBoxInfo.Text;

                NetworkStream stream = tcpClient.GetStream();
                byte[] byteArray = new byte[1024];
                while (true)
                {
                    int length = stream.Read(byteArray, 0, 1024);//스트림 바이트 데이터를 byteArray 버퍼에 저장
                    //length는 클라이언트가 전송한 실제 바이트 길이
                    string receiveMessage = Encoding.Unicode.GetString(byteArray, 0, length);
                    this.textBoxInfo.Text = "수신:" + receiveMessage + "-" +
                        DateTime.Now.ToShortTimeString() + "\r\n" + this.textBoxInfo.Text;
                }
            });
            acceptThread.IsBackground = true;
            acceptThread.Start();
        }
    }
}Code language: C# (cs)

WinForms + TcpClient / TcpListener 기반 구현:
클라이언트에서 사용자 정의 텍스트를 계속 전송하며,【종료】를 입력하면 연결을 끊고 프로그램을 종료합니다

이 예제는 멀티스레드 UI 정지 문제를 간단하게 처리했지만 올바른 구현 방식은 아래와 같습니다.
Control.CheckForIllegalCrossThreadCalls = false;권장하지 않는 강제 우회 코드입니다. 실제 프로젝트에서는 Invoke/BeginInvoke를 사용해 크로스스레드 컨트롤 업데이트를 진행해야 합니다.

1. 서버 측

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;

namespace TcpServerDemo
{
    public partial class Form1 : Form
    {
        private TcpListener listener;
        private TcpClient tcpClient;

        public Form1()
        {
            InitializeComponent();
            // 학습용 데모 코드이므로 실제 서비스에서 사용 금지
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        private void btnStartServer_Click(object sender, EventArgs e)
        {
            //UI 블로킹 방지를 위해 새 스레드 실행
            new Thread(() =>
            {
                IPAddress ip = IPAddress.Parse(textBoxIP.Text);
                listener = new TcpListener(ip, Convert.ToInt32(textBoxPort.Text));
                listener.Start();
                AppendLog($"서버 시작‑{DateTime.Now.ToShortTimeString()}");

                tcpClient = listener.AcceptTcpClient();
                AppendLog($"클라이언트 연결 완료‑{DateTime.Now.ToShortTimeString()}");

                NetworkStream stream = tcpClient.GetStream();
                byte[] byteArray = new byte[1024];
                while (true)
                {
                    int length = stream.Read(byteArray, 0, 1024);
                    if (length <= 0)
                    {
                        AppendLog("클라이언트 연결이 끊겼습니다");
                        break;
                    }
                    string receiveMessage = Encoding.Unicode.GetString(byteArray, 0, length);
                    AppendLog($"수신:{receiveMessage}{DateTime.Now.ToShortTimeString()}");
                }
                tcpClient.Close();
                listener.Stop();
            }).Start();
        }

        //텍스트박스에 로그 추가
        private void AppendLog(string msg)
        {
            textBoxInfo.Text = msg + "\r\n" + textBoxInfo.Text;
        }
    }
}Code language: C# (cs)

2. 클라이언트 코드

연속 입력 기능 구현,「종료」입력 시 통신 종료

클라이언트 화면에 준비해야 할 컨트롤:

  • textBoxServerIp:서버 IP 주소
  • textBoxPort:포트 번호
  • textBoxSend:전송 메시지 입력 상자
  • btnConnect:연결 버튼
  • btnSend:전송 버튼
using System;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace TcpClientDemo
{
    public partial class ClientForm : Form
    {
        private TcpClient client;
        private NetworkStream stream;
        private bool isConnected = false;

        public ClientForm()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        //서버에 연결
        private void btnConnect_Click(object sender, EventArgs e)
        {
            try
            {
                client = new TcpClient();
                client.Connect(textBoxServerIp.Text, Convert.ToInt32(textBoxPort.Text));
                stream = client.GetStream();
                isConnected = true;
                MessageBox.Show("연결 성공, 메시지를 보낼 수 있습니다!");
            }
            catch (Exception ex)
            {
                MessageBox.Show("연결 실패:" + ex.Message);
            }
        }

        //메시지 전송 핵심 로직
        private void btnSend_Click(object sender, EventArgs e)
        {
            if (!isConnected)
            {
                MessageBox.Show("먼저 서버에 연결하십시오!");
                return;
            }
            string content = textBoxSend.Text.Trim();
            if (string.IsNullOrEmpty(content))
                return;

            //종료 명령 감지
            if (content == "종료")
            {
                byte[] exitData = Encoding.Unicode.GetBytes(content);
                stream.Write(exitData, 0, exitData.Length);

                //리소스 해제
                stream.Close();
                client.Close();
                isConnected = false;
                MessageBox.Show("연결이 종료되었습니다");
                return;
            }

            //일반 메시지 전송
            byte[] data = Encoding.Unicode.GetBytes(content);
            stream.Write(data, 0, data.Length);
            textBoxSend.Clear();
        }
    }
}Code language: C# (cs)
static void Main(string[] args)
{
    TcpClient client = new TcpClient();
    client.Connect("127.0.0.1", 8899);
    NetworkStream stream = client.GetStream();
    while (true)
    {
        Console.Write("전송할 내용 입력:");
        string msg = Console.ReadLine();
        byte[] buf = Encoding.Unicode.GetBytes(msg);
        stream.Write(buf,0,buf.Length);
        if (msg == "종료")
        {
            stream.Close();
            client.Close();
            break;
        }
    }
}Code language: JavaScript (javascript)

필요하시다면 전체 코드를완전 비동기 async/await 구문으로 재작성해 보조 스레드와 크로스스레드 검사 비활성화 같은 비표준 방식을 완전히 없앨 수 있습니다.

클라이언트 연속 메시지 전송

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다