처음 프로그래밍을 접하게 된 후 가장 먼저 해보는 통신 중에 하나 소켓 통신일 것입니다. 보통 모든 개발언에서 가장 기본적으로 배우게 되고, 이 소켓 통신을 이용해서 채팅 프로그램이나 간단한 네트워크 게임 등의 응용프로그램을 만들어보기 시작할 것입니다. 저도 대학교 때는 소켓통신을 이용하여 App 간 통신을 하도록 하거나 H/W와의 메시지를 주고받아 구동하도록 하는 프로젝트도 진행했었습니다. 당시에는 C++로 진행했었습니다. 오늘은 소켓통신에 대해서 알아보고 간단하게 C#으로 예제를 구현해 보도록 하겠습니다.
소켓 통신(Socket Communication)은 컴퓨터 네트워크에서 프로세스 간에 데이터를 교환하기 위한 메커니즘입니다. 소켓은 컴퓨터 간에 통신을 담당하는 소프트웨어적인 장치로, 일반적으로 TCP/IP 프로토콜을 기반으로 합니다.
소켓 통신은 다음과 같은 주요 특징을 가지고 있습니다:
- 통신 방식:
- TCP (Transmission Control Protocol): 연결 지향적인 통신 프로토콜로, 안정적인 데이터 전송을 보장합니다. 데이터의 손실이나 순서 변경이 거의 없으며, 신뢰성 있는 통신이 필요한 경우에 주로 사용됩니다.
- UDP (User Datagram Protocol): 비연결성이며 신뢰성이 낮은 프로토콜로, 빠른 데이터 전송이 요구되는 경우에 사용됩니다. 일부 데이터의 손실이나 순서 변경이 허용됩니다.
- 서버와 클라이언트:
- 서버(Server): 서비스를 제공하고, 클라이언트의 연결 요청을 받아들이며, 데이터를 주고받는 역할을 합니다.
- 클라이언트(Client): 서버에 연결을 요청하고, 서버와 데이터를 주고받는 역할을 합니다.
- 포트 (Port): 소켓 통신에서는 포트를 사용하여 특정 프로세스와 연결됩니다. 서버 및 클라이언트는 서로 다른 포트를 사용하여 통신합니다.
- 소켓 타입:
- 스트림 소켓(Stream Socket): 연결 지향적인 통신을 제공하며, 신뢰성 있는 데이터 스트림을 전송합니다. 주로 TCP 소켓이 이에 해당합니다.
- 데이터그램 소켓(Datagram Socket): 비연결성 통신을 제공하며, UDP와 관련이 있습니다.
- 통신 프로세스:
- 바인딩(Binding): 소켓을 특정 주소와 포트에 연결하는 과정입니다.
- 리스닝(Listening): 서버 소켓이 클라이언트의 연결 요청을 수신 대기하는 상태입니다.
- 연결(Connection): 클라이언트가 서버에 연결을 요청하고, 서버가 이를 수락하는 과정입니다.
- 데이터 교환(Data Exchange): 서버와 클라이언트 간에 데이터를 주고받는 과정입니다.
- 종료(Termination): 통신이 완료되면 소켓을 닫아 리소스를 해제합니다.
소켓 통신은 네트워크 프로그래밍에서 매우 중요한 부분이며, 웹 브라우저와 웹 서버 간의 통신에서부터 다양한 클라이언트-서버 응용프로그램까지 다양한 분야에서 사용됩니다. 프로그래밍 언어 및 플랫폼에 따라 소켓 통신을 지원하는 API가 다르지만, 대표적으로 C#, C/C++, Java, Python 등에서는 소켓 프로그래밍을 위한 API를 제공하고 있습니다.
아래는 서버 로컬 호스트의 8080번 포트에서 클라이언트의 연결을 기다리고, 클라이언트는 서버에 연결한 후 사용자로부터 메시지를 입력받아 서버로 전홍하고, 서버는 받은 메시지를 다시 클라이언트에게 돌려주는 간단한 코드입니다.
C# 서버 코드
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
class Server
{
static void Main()
{
// 서버 소켓 생성
TcpListener serverSocket = new TcpListener(IPAddress.Any, 8080);
serverSocket.Start();
Console.WriteLine("서버 시작. 대기 중...");
// 클라이언트 연결 대기
TcpClient clientSocket = serverSocket.AcceptTcpClient();
Console.WriteLine("클라이언트 연결됨.");
// 네트워크 스트림 생성
NetworkStream networkStream = clientSocket.GetStream();
byte[] bytesFrom = new byte[10025];
string dataFromClient = null;
while (true)
{
try
{
// 클라이언트로부터 데이터 읽기
networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);
dataFromClient = Encoding.UTF8.GetString(bytesFrom);
dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
Console.WriteLine("클라이언트로부터 수신한 메시지: " + dataFromClient);
// 클라이언트에게 데이터 전송
string serverResponse = "서버에서 수신한 메시지: " + dataFromClient;
Byte[] sendBytes = Encoding.UTF8.GetBytes(serverResponse);
networkStream.Write(sendBytes, 0, sendBytes.Length);
networkStream.Flush();
Console.WriteLine("클라이언트에게 응답 전송: " + serverResponse);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
}
클라이언트 코드
using System;
using System.Net.Sockets;
using System.Text;
class Client
{
static void Main()
{
try
{
TcpClient clientSocket = new TcpClient();
clientSocket.Connect("127.0.0.1", 8080);
Console.WriteLine("서버에 연결됨.");
while (true)
{
Console.Write("메시지 입력: ");
string clientMessage = Console.ReadLine();
NetworkStream networkStream = clientSocket.GetStream();
byte[] outStream = Encoding.UTF8.GetBytes(clientMessage + "$");
networkStream.Write(outStream, 0, outStream.Length);
networkStream.Flush();
byte[] inStream = new byte[10025];
networkStream.Read(inStream, 0, (int)clientSocket.ReceiveBufferSize);
string serverResponse = Encoding.UTF8.GetString(inStream);
serverResponse = serverResponse.Substring(0, serverResponse.IndexOf("$"));
Console.WriteLine("서버로부터 수신한 응답: " + serverResponse);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
'IT, 컴퓨터' 카테고리의 다른 글
허브(Hub)와 공유기(Router)의 차이점 (46) | 2023.11.16 |
---|---|
격돌 32비트 게임의 시대 20세기말 "플레이스테이션 VS 세턴" (87) | 2023.11.15 |
무선인터넷(WIFI)의 역사에 대해서 (28) | 2023.11.13 |
키보드의 종류와 키보드 역사에 대해서 (41) | 2023.11.12 |
프린터기의 역사... (27) | 2023.11.11 |