C#에서 TCP/IP 소켓을 사용하여 클라이언트와 서버를 구현하는 두 가지 방법이 있습니다. TcpClient와 TcpListener 클래스를 사용하는 방법과 Socket 클래스를 직접 사용하는 방법입니다. 두 가지 방법 모두 효과적이지만, Socket 클래스를 직접 사용하는 방법이 더 유연하고 낮은 수준의 제어를 제공합니다.
아래는 Socket 클래스를 사용하여 TCP 서버와 클라이언트를 구현한 예제입니다. 이 예제에서는 IPEndPoint를 사용하여 네트워크 주소와 포트 번호를 설정하고, 소켓을 통해 데이터를 송수신하는 과정을 보여줍니다.
TCPServer 프로젝트의 Program.cs 파일에 다음 코드를 작성합니다.
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
// IP 주소와 포트를 설정합니다.
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
int port = 11000;
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, port);
// 소켓을 생성하고 바인딩합니다.
using Socket listener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(localEndPoint);
listener.Listen(100);
Console.WriteLine("서버가 시작되었습니다.");
while (true)
{
// 클라이언트 연결을 기다립니다.
Socket handler = await listener.AcceptAsync();
Console.WriteLine("클라이언트가 연결되었습니다.");
// 클라이언트로부터 데이터를 수신합니다.
byte[] buffer = new byte[1024];
int bytesReceived = await handler.ReceiveAsync(buffer, SocketFlags.None);
string receivedMessage = Encoding.UTF8.GetString(buffer, 0, bytesReceived);
Console.WriteLine("수신된 메시지: " + receivedMessage);
// 받은 데이터를 다시 클라이언트로 보냅니다.
await handler.SendAsync(buffer, SocketFlags.None);
Console.WriteLine("메시지를 다시 보냈습니다.");
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
}
}
TCPClient 프로젝트의 Program.cs 파일에 다음 코드를 작성합니다.
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
// 서버 도메인 이름과 포트를 설정합니다.
string serverDomain = "127.0.0.1";
int port = 11000;
// DNS를 사용하여 서버의 IP 주소를 가져옵니다.
IPHostEntry hostEntry = await Dns.GetHostEntryAsync(serverDomain);
IPAddress ipAddress = hostEntry.AddressList[0];
IPEndPoint remoteEndPoint = new IPEndPoint(ipAddress, port);
// 소켓을 생성하고 서버에 연결합니다.
using Socket client = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
await client.ConnectAsync(remoteEndPoint);
Console.WriteLine("서버에 연결되었습니다.");
// 서버로 보낼 메시지를 설정합니다.
string message = "안녕하세요, 서버!";
byte[] data = Encoding.UTF8.GetBytes(message);
// 데이터를 서버로 보냅니다.
await client.SendAsync(data, SocketFlags.None);
Console.WriteLine("메시지를 보냈습니다: " + message);
// 서버로부터 데이터를 수신합니다.
byte[] buffer = new byte[1024];
int bytesReceived = await client.ReceiveAsync(buffer, SocketFlags.None);
string receivedMessage = Encoding.UTF8.GetString(buffer, 0, bytesReceived);
Console.WriteLine("서버로부터 수신된 메시지: " + receivedMessage);
client.Shutdown(SocketShutdown.Both);
client.Close();
}
}
서버 코드
IPAddress.Parse("127.0.0.1")와 포트 번호 11000을 사용하여 IPEndPoint 객체를 생성합니다.
Socket 객체를 생성하고, Bind 메서드로 로컬 엔드포인트에 바인딩합니다.
Listen 메서드로 소켓을 수신 대기 상태로 설정하고, AcceptAsync 메서드로 클라이언트 연결을 기다립니다.
클라이언트로부터 데이터를 수신하고, 받은 데이터를 다시 클라이언트로 보냅니다.
클라이언트 코드
Dns.GetHostEntryAsync 메서드를 사용하여 서버 도메인 이름을 IP 주소로 변환합니다.
Socket 객체를 생성하고, ConnectAsync 메서드를 사용하여 서버에 연결합니다.
메시지를 서버로 보내고, 서버로부터 데이터를 수신합니다.
이 코드는 Socket 클래스를 사용하여 TCP 서버와 클라이언트를 구현하는 방법을 보여줍니다. 이 방법은 보다 낮은 수준에서 소켓 통신을 제어할 수 있어 유연성이 높습니다. 위의 예제는 로컬 호스트를 사용하지만, 실제 네트워크 환경에서는 원격 서버의 IP 주소와 포트를 사용하여 통신할 수 있습니다.