using System;
using System.Diagnostics; // 현재 프로세스 정보를 얻기 위한 네임스페이스
using System.Net; // 네트워크 관련 클래스를 사용하기 위한 네임스페이스
using System.Net.Sockets; // 소켓 통신을 위한 네임스페이스
using System.Text; // 문자열 인코딩을 위한 네임스페이스
// TcpListener/ TcpClient 클래스를 활용한 '메아리 서버 구현'하기
// 클라이언트가 보낸 메시지를 서버가 그대로 돌려보내는 프로그램
namespace EchoServer
{
class MainApp
{
static void Main(string[] args)
{
if (args.Length < 1) // 명령줄 인수가 1개 미만이면
{
Console.WriteLine("사용법 : {0} <Bind IP>", Process.GetCurrentProcess().ProcessName); // 사용법 출력
return; // 프로그램 종료
}
string bindIp = args[0]; // 첫 번째 명령줄 인수를 bindIp에 저장
const int bindPort = 5425; // 포트 번호 5425를 상수로 정의
TcpListener server = null; // TcpListener 객체를 선언하고 null로 초기화
try
{
IPEndPoint localAddress = new IPEndPoint(IPAddress.Parse(bindIp), bindPort);
// IP 주소와 포트 번호를 사용하여 IPEndPoint 객체 생성
// IPEndPoint: IP 통신에 필요한 'IP 주소'와 '포트 번호'를 나타냅니다.
server = new TcpListener(localAddress); // TcpListener 객체 생성
server.Start(); // 서버 시작
// server 객체는 클라이언트가 연결 요청해오기를 기다리기 '시작'합니다.
Console.WriteLine("메아리 서버 시작... "); // "메아리 서버 시작... " 메시지 출력
while (true) // 무한 루프
{
TcpClient client = server.AcceptTcpClient(); // 클라이언트 접속 대기
Console.WriteLine("클라이언트 접속 : {0} ", ((IPEndPoint)client.Client.RemoteEndPoint).ToString()); // 클라이언트 접속 정보 출력
NetworkStream stream = client.GetStream(); // 클라이언트와 통신할 NetworkStream 객체 가져오기
int length; // 데이터 길이를 저장할 변수
string data = null; // 데이터를 저장할 변수
byte[] bytes = new byte[256]; // 데이터를 저장할 바이트 배열
while ((length = stream.Read(bytes, 0, bytes.Length)) != 0) // 클라이언트에서 데이터를 읽어옴
{
data = Encoding.Default.GetString(bytes, 0, length); // 바이트 배열을 문자열로 변환
Console.WriteLine(String.Format("수신: {0}", data)); // 수신 데이터 출력
byte[] msg = Encoding.Default.GetBytes(data); // 문자열을 바이트 배열로 변환
stream.Write(msg, 0, msg.Length); // 클라이언트에 데이터를 씀
Console.WriteLine(String.Format("송신: {0}", data)); // 송신 데이터 출력
}
stream.Close(); // NetworkStream 닫기
client.Close(); // TcpClient 닫기
}
}
catch (SocketException e) // SocketException 예외 발생 시
{
Console.WriteLine(e); // 예외 정보 출력
}
finally // 예외 발생 여부와 관계없이 항상 실행
{
server.Stop(); // 서버 중지
}
Console.WriteLine("서버를 종료합니다."); // "서버를 종료합니다." 메시지 출력
}
}
}
코드 설명
using System;
using System.Diagnostics; // 현재 프로세스 정보를 얻기 위한 네임스페이스
using System.Net; // 네트워크 관련 클래스를 사용하기 위한 네임스페이스
using System.Net.Sockets; // 소켓 통신을 위한 네임스페이스
using System.Text; // 문자열 인코딩을 위한 네임스페이스
namespace EchoServer
{
class MainApp
{
static void Main(string[] args)
{
if (args.Length < 1) // 명령줄 인수가 1개 미만이면
{
Console.WriteLine("사용법 : {0} <Bind IP>", Process.GetCurrentProcess().ProcessName); // 사용법 출력
return; // 프로그램 종료
}
string bindIp = args[0]; // 첫 번째 명령줄 인수를 bindIp에 저장
const int bindPort = 5425; // 포트 번호 5425를 상수로 정의
TcpListener server = null; // TcpListener 객체를 선언하고 null로 초기화
try
{
IPEndPoint localAddress = new IPEndPoint(IPAddress.Parse(bindIp), bindPort); // IP 주소와 포트 번호를 사용하여 IPEndPoint 객체 생성
server = new TcpListener(localAddress); // TcpListener 객체 생성
server.Start(); // 서버 시작
Console.WriteLine("메아리 서버 시작... "); // "메아리 서버 시작... " 메시지 출력
while (true) // 무한 루프
{
TcpClient client = server.AcceptTcpClient(); // 클라이언트 접속 대기
Console.WriteLine("클라이언트 접속 : {0} ", ((IPEndPoint)client.Client.RemoteEndPoint).ToString()); // 클라이언트 접속 정보 출력
NetworkStream stream = client.GetStream(); // 클라이언트와 통신할 NetworkStream 객체 가져오기
int length; // 데이터 길이를 저장할 변수
string data = null; // 데이터를 저장할 변수
byte[] bytes = new byte[256]; // 데이터를 저장할 바이트 배열
while ((length = stream.Read(bytes, 0, bytes.Length)) != 0) // 클라이언트에서 데이터를 읽어옴
{
data = Encoding.Default.GetString(bytes, 0, length); // 바이트 배열을 문자열로 변환
Console.WriteLine(String.Format("수신: {0}", data)); // 수신 데이터 출력
byte[] msg = Encoding.Default.GetBytes(data); // 문자열을 바이트 배열로 변환
stream.Write(msg, 0, msg.Length); // 클라이언트에 데이터를 씀
Console.WriteLine(String.Format("송신: {0}", data)); // 송신 데이터 출력
}
stream.Close(); // NetworkStream 닫기
client.Close(); // TcpClient 닫기
}
}
catch (SocketException e) // SocketException 예외 발생 시
{
Console.WriteLine(e); // 예외 정보 출력
}
finally // 예외 발생 여부와 관계없이 항상 실행
{
server.Stop(); // 서버 중지
}
Console.WriteLine("서버를 종료합니다."); // "서버를 종료합니다." 메시지 출력
}
}
}
코드 설명
이 C# 코드는 TcpListener 클래스를 사용하여 에코 서버를 구현하는 예제입니다. 에코 서버는 클라이언트에서 받은 데이터를 그대로 다시 클라이언트에게 전송하는 서버입니다.
Main 메서드:TcpListener를 생성합니다.try 블록에서 서버를 시작하고 클라이언트 접속을 대기합니다.NetworkStream을 사용하여 데이터를 주고받습니다.catch 블록에서 SocketException 예외를 처리합니다.finally 블록에서 서버를 중지합니다.클래스 및 메서드 설명
TcpListener: TCP 네트워크 서비스를 수신 대기하는 데 사용됩니다.TcpClient: TCP 네트워크 서비스에 연결하는 데 사용됩니다.NetworkStream: 네트워크 스트림을 통해 데이터를 주고받는 데 사용됩니다.Encoding.Default: 시스템의 기본 인코딩을 가져옵니다.server.AcceptTcpClient(): 클라이언트 접속을 대기하고, 클라이언트가 접속하면 TcpClient 객체를 반환합니다.client.GetStream(): 클라이언트와 통신할 NetworkStream 객체를 가져옵니다.stream.Read(): 스트림에서 데이터를 읽습니다.stream.Write(): 스트림에 데이터를 씁니다.server.Stop(): 서버를 중지합니다.TcpListener와 TcpClient 클래스TcpListener와 TcpClient 클래스는 TCP 소켓 통신을 위한 클래스입니다.
TcpListener는 서버에서 클라이언트의 연결 요청을 수신 대기하는 데 사용되고, TcpClient는 클라이언트에서 서버에 연결하는 데 사용됩니다.
이 코드에서는 TcpClient 클래스를 사용하여 에코 서버를 구현했습니다. 따라서 "TCP 소켓 통신을 사용하여 에코 클라이언트를 만들었습니다"
TCP 소켓 통신은 인터넷에서 데이터를 주고받는 방식 중 하나입니다.
소켓은 데이터를 주고받는 창구라고 생각하면 됩니다.
TCP는 데이터를 안정적으로 전송하기 위한 규칙입니다.
TCP 소켓 통신은 클라이언트와 서버 사이에서 이루어지는데,
TCP 소켓 통신은 인터넷에서 다양한 서비스를 제공하는 데 사용되는 중요한 기술입니다.