<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>C | 정진영의 포트폴리오</title><link>https://wjdwlsdud.github.io/tags/c/</link><atom:link href="https://wjdwlsdud.github.io/tags/c/index.xml" rel="self" type="application/rss+xml"/><description>C</description><generator>Hugo Blox Builder (https://hugoblox.com)</generator><language>ko</language><lastBuildDate>Wed, 26 Jun 2024 00:00:00 +0000</lastBuildDate><image><url>https://wjdwlsdud.github.io/media/sharing.jpg</url><title>C</title><link>https://wjdwlsdud.github.io/tags/c/</link></image><item><title>리눅스 TCP 채팅 프로그램</title><link>https://wjdwlsdud.github.io/projects/linux/</link><pubDate>Wed, 26 Jun 2024 00:00:00 +0000</pubDate><guid>https://wjdwlsdud.github.io/projects/linux/</guid><description>&lt;p&gt;리눅스 시스템 프로그래밍 수업에서 배운 내용을 바탕으로 간단한 멀티-클라이언트 TCP 채팅 프로그램을 프로젝트로 구현해 보았습니다.&lt;/p&gt;
&lt;p&gt;C언어의 소켓(Socket) 통신과 멀티스레드(pthread) 개념을 직접 적용해 볼 수 있었던 의미 있는 경험이라, 프로젝트의 구조와 핵심 동작 원리, 그리고 배운 점들을 정리해 보려고 합니다.&lt;/p&gt;
&lt;h2 id="1-프로젝트-개요"&gt;1. 프로젝트 개요&lt;/h2&gt;
&lt;p&gt;이 프로그램은 1개의 서버와 다수의 클라이언트가 TCP/IP 프로토콜을 기반으로 실시간 채팅을 주고받을 수 있는 간단한 콘솔(터미널) 기반 채팅방입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;주요 기술&lt;/strong&gt;: C언어, TCP/IP 소켓 프로그래밍, pthread (멀티스레딩)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;핵심 기능&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;서버: 다수의 클라이언트 접속을 동시에 관리합니다.&lt;/li&gt;
&lt;li&gt;브로드캐스팅: 한 클라이언트가 보낸 메시지를, 보낸 사람을 제외한 모든 접속자에게 전송합니다.&lt;/li&gt;
&lt;li&gt;멀티 채팅: 여러 사용자가 동시에 메시지를 보내고 받을 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="2-핵심-아키텍처-어떻게-동시에"&gt;2. 핵심 아키텍처: 어떻게 동시에?&lt;/h2&gt;
&lt;p&gt;채팅 프로그램의 핵심은 &amp;lsquo;어떻게 여러 명의 요청을 동시에 처리하는가&amp;rsquo;입니다. accept(), recv(), fgets() 같은 함수들은 기본적으로 &amp;lsquo;블로킹(Blocking)&amp;rsquo; 방식으로 동작합니다. 즉, 자기 차례가 올 때까지 프로그램 전체를 멈추고 기다립니다.&lt;/p&gt;
&lt;p&gt;이 문제를 해결하기 위해 멀티스레딩을 사용했습니다.&lt;/p&gt;
&lt;p&gt;⚙️ &lt;strong&gt;서버: 클라이언트마다 전담 스레드 (Thread-per-Client)&lt;/strong&gt;
서버는 동시에 여러 클라이언트의 접속 요청과 메시지 수신을 처리해야 합니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;메인 스레드는 accept() 함수로 클라이언트의 새로운 접속을 기다립니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;새로운 클라이언트가 접속하면, pthread_create()를 호출해 그 클라이언트만을 전담하는 스레드(client_chat)를 하나 생성합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;이 전담 스레드는 recv() 함수를 통해 해당 클라이언트로부터 메시지가 올 때까지 대기합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;메인 스레드는 다시 accept()로 돌아가 다음 접속자를 기다립니다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;즉, &amp;lsquo;접속 처리&amp;rsquo; 스레드와 &amp;lsquo;클라이언트별 메시지 수신&amp;rsquo; 스레드들이 각자 독립적으로 동시에 실행됩니다.&lt;/p&gt;
&lt;p&gt;메시지를 받으면 send_msg 함수가 모든 클라이언트 리스트(clientList)를 순회하며 메시지를 전파(브로드캐스팅)합니다.&lt;/p&gt;
&lt;p&gt;💻 &lt;strong&gt;클라이언트: &amp;lsquo;보내는 스레드&amp;rsquo;와 &amp;lsquo;받는 스레드&amp;rsquo;의 분리&lt;/strong&gt;
클라이언트 역시 큰 숙제가 있습니다. 바로 내가 메시지를 입력하는 중에도 다른 사람의 메시지를 실시간으로 받아야 한다는 것입니다.&lt;/p&gt;
&lt;p&gt;만약 스레드가 하나라면, fgets()로 내 입력을 기다리는 동안 recv()가 실행될 수 없어 다른 사람의 메시지를 받지 못합니다.&lt;/p&gt;
&lt;p&gt;이 문제를 해결하기 위해 클라이언트 프로그램을 2개의 스레드로 분리했습니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;메인 스레드 (main 함수): 사용자의 키보드 입력(fgets)을 받아 서버로 전송(send)하는 &amp;lsquo;보내는&amp;rsquo; 역할만 전담합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;수신 스레드 (receive 함수): pthread_create()로 생성되며, 오직 서버로부터 메시지를 받는(recv) &amp;lsquo;받는&amp;rsquo; 역할만 전담합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이렇게 두 스레드가 각자의 역할을 나눠 갖기 때문에, 내가 메시지를 한창 입력하고 있는 중에도 receive 스레드는 서버가 보낸 다른 사람의 메시지를 화면에 실시간으로 출력해줄 수 있습니다.&lt;/p&gt;
&lt;p&gt;위에 첨부된 링크로 코드를 확인하실 수 있습니다!&lt;/p&gt;</description></item></channel></rss>