1. TCP/IP
컴퓨터 사이에 데이터를 주고받으려면 나름대로의 규칙이 필요합니다. 어떠한 방법으로 어떠한 방식을 통해 전송할 것인가를 정해야 하고 그래야 데이터를 그 약속대로 보내고 받을 수 있을 것입니다.
데이터를 주고받기 위한 이러한 규칙을 '프로토콜'이라고 부르며 세상에 존재하는 다양한 프로토콜 중 'TCP/IP'는 사실상 인터넷의 표준 프로토콜이라 할 수 있습니다.
TCP/IP는 논리적으로 몇개의 계층구조로 나누어지는데 최상단 응용계층부터 링크(네트워크 접근) 계층까지 각 계층마다 층을 이루고 있으며 이러한 층을 'TCP/IP 스택'이라고 합니다.
웹 브라우저에서 부터 카톡과 같은 메신저나 유튜브 등 다양한 인터넷 서비스들이 이 'TCP/IP 프로토콜'을 통해 이루어지고 있습니다.
● 패킷
인터넷상에서 주고 받는 '데이터'를 의미하며 본래 전송하고자 하는 데이터뿐만 아니라 TCP/IP 프로토콜을 위한 각 계층의 정보까지 포함하고 있는 형태를 말합니다.
● 링크 계층
WIFI나 모뎀, LAN케이블등 물리적인 연결 부분을 담당합니다. 해당 계층에서 가장 먼저 패킷을 받으며 패킷에서 물리적 연결 정보를 제거 후 다시 인터넷 계층으로 패킷을 전달합니다.
● 인터넷 계층
패킷을 보낼때 패킷을 분할하거나 패킷을 받을 때 패킷을 재조립하는 계층입니다. 이때 사용되는 규칙이 '인터넷 프로토콜' 즉, IP라고 하며 TCP/IP에서 IP가 여기에 해당합니다. 또한 데이터를 보낼 때 데이터를 수신할 목적지 정보도 함께 다루게 되는데 흔히 이 목적지 정보를 'IP 주소'라고 합니다.
● 전송 계층
실제 데이터를 전송하는 계층입니다. 패킷을 보낼때 패킷 사이에 순서를 조정하거나 패킷 전송 중 유실되는 패킷이 있으면 해당 패킷을 재전송하는 등의 역할을 담당하면서 실제 데이터 전송에 필요한 연결성과 신뢰성을 제공합니다. 물론 이러한 연결성과 신뢰성을 제공하려면 패킷 전송에 순서를 정하고 제대로 패킷이 전송되었느가를 확인해야 하는 과정을 거쳐야 하는데 이 과정에서 데이터가 전송되는 '속도'문제에 영향을 주게 됩니다.
대용량의 패킷을 전송해야 하는 경우 TCP는 속도에 영향을 주더라도 안정적인 전송을 위해 꼭 필요한 부분입니다. 하지만 한번에 보낼 수 있는 아주 작은 패킷을 전송하거나 데이터를 전송한 이후 상대방이 제대로 데이터를 수신했는가를 확인할 필요가 없는 경우라면 굳이 TCP의 역할이 필요하지 않습니다. 바로 이러한 상황에 대비해 UDP(User Datagram Protocol)라는 프로토콜도 존재하는데 TCP가 가진 연결성/신뢰성을 제공하지는 않지만 덕분에 빠른 속도로 데이터를 전송할 수 있다는 특징이 있습니다. 대부분 인터넷이 아닌 내부적으로 데이터를 전송하는 경우에 많이 사용되는 프로토콜입니다.
한편 전송 계층에서도 데이터를 전송할때 나름대로의 규칙이 사용되는데 그 규칙이 '전송 제어 프로토콜(Transmission Control Protocol)'이며 TCP/IP에서 TCP가 여기에 해당합니다.
● 응용 계층
애플리케이션 계층이라고도 하며 프로그램에 필요한 프로토콜이 정의되는 부분입니다. 웹 브라우저의 경우 HTTP(Hyper Text Transfer Protocol)나 파일 전송 시 사용되는 FTP(File Transfer Protocol)등을 생각할 수 있습니다.
물론 HTTP나 FTP등 잘 알려진 응용 계층 프로토콜 외에도 어떤 데이터 전송에 필요한 프로그램을 만드는 경우에 프로그램끼리 데이터를 주고받기 위한 규칙이 정의될 수 있는데 그 규칙도 응용 계층에서 사용되는 프로토콜로서 취급될 수 있습니다.
2. IP 주소
우리가 흔히 말하는 IP는 211.194.160.140처럼 4개의 단위로 점(.)을 통해 구분되는 숫자를 말하며 이러한 형태의 IP주소를 'IPv4'라고 합니다. 인터넷을 사용하기 위해서는 이런 IP가 예외 없이 반드시 필요합니다. 하지만 지구 상에는 많은 컴퓨터와 스마트폰 등 인터넷을 사용하기 위한 수많은 기기들이 있는데 해당 기기마다 IP를 할당하기에는 할당할 수 있는 수가 너무 부족하므로 이를 대체하기 위해 DHCP라는 개념이 등장했습니다.
DHCP는 Dynamic Host Configuration Protocol로서 쉽게말해 하나의 IP를 인터넷 사용이 필요한 여러 개의 기기들이 서로 공유하며 사용하는 것을 형태를 말합니다. 각 기기마다 독립된 IP를 모두 할당하지 않아도 되므로 IP부족을 어느 정도 해결하는데 큰 기여를 하고 있습니다.
IP부족을 해결하기위한 또 다른 방안으로 IPv6라는 체계의 IP가 사용되기도 합니다. IPv4 체계의 주소보다 훨씬 긴 문자와 숫자가 결합된 주소 형태를 제공하는데 거의 무제한에 가까운 IP주소를 만들어 낼 수 있어서 DHCP를 사용하지 않더라도 지구 상에 존재하는 모든 기기에 독립된 주소를 할당하는 것이 가능합니다.
3. 포트
상대 컴퓨터와 데이터를 주고 받으려면 IP주소뿐 아니라 포트번호라는 것도 필요합니다. IP는 주소고 포트는 일종의 '문'과 같은 역할을 하는데 대략 0~65535 사이 값을 사용합니다.
많이 알려진 프로그램의 경우 사용하는 포트는 미리 정해져 있는데 인터넷 웹브라우저의 경우 80번, FTP는 21번, 메일을 주고받는 SMTP의 경우에는 25번이 사용됩니다. 대부분 1~1023 사이의 번호가 정해진 번호로 사용되므로 네트워크를 이용하는 별도의 프로그램을 만드는 경우에는 이 범위의 포트 사용을 피하는 것이 좋습니다.
4. TcpListener와 TcpClient
.NET에서 TCP/IP 통신을 위해서는 TcpListener와 TcpClient class를 사용할 수 있으며 좀 더 세밀한 제어를 위해서는 Socket class를 사용할 수도 있습니다.
server에서는 TcpListener와 TcpClient class모두가 사용되며 client에서는 TcpClient가 사용됩니다. TcpListener는 server에서 연결을 대기하고 있다가 TcpClient에서 연결 요청이 오면 그때 client와 연결을 수립하는 역할을 하며 일단 client와 server 간에 연결이 이루어지면 양쪽 모두 TcpClient를 통해서 통신을 하게 됩니다.
TcpClient class에는 GetStream() method를 통해서 반환되는 NetworkStream객체를 사용해 데이터를 송/수신할 수 있는데 수신에는 Read() method가 송신에는 Write() method가 사용됩니다.
server나 client모두 연결을 종료하는 경우 NetworkStream과 TcpClient에서 Close()메서드를 호출하며 server에서는 추가적으로 TcpListener의 Stop() method를 호출함으로써 server를 종료합니다.
using System;
using System.Net;
using System.Net.Sockets;
using static System.Console;
using System.Text;
namespace app
{
class Program
{
static void Main(string[] args)
{
IPEndPoint serverAddress = new IPEndPoint(IPAddress.Parse("172.27.145.29"), 3000);
TcpListener server = new TcpListener(serverAddress);
server.Start();
WriteLine("서버 시작됨");
while (true)
{
TcpClient client = server.AcceptTcpClient();
WriteLine("클라이언트 접속");
NetworkStream stream = client.GetStream();
int length = 0;
string data = string.Empty;
byte[] bytes = new byte[256];
while ((length = stream.Read(bytes, 0, bytes.Length)) != 0)
{
data = Encoding.Default.GetString(bytes, 0, length);
WriteLine(data);
byte[] message = Encoding.Default.GetBytes(data);
stream.Write(message, 0, message.Length);
}
stream.Close();
client.Close();
break;
}
server.Stop();
WriteLine("서버 종료");
}
}
}
server에서는 TcpListener에서 start() method를 호출하는 것으로 server를 시작합니다. 그런 후 client의 연결을 감지하기 위해 AcceptTcpClient() method를 호출했는데 이때부터는 client로부터 요청이 들어올 때까지 대기하게 되고 연결 요청이 오면 그때 AcceptTcpClient() 메서드에서 TcpClient객체를 반환하게 되고 이후의 처리가 진행됩니다.
Client로부터의 data 수신은 NetworkStream의 Read() method로 이루어지며 이렇게 읽어온 data를 Write() method를 통해 다시 client에게 보내고 있습니다. 그런 후 close() method를 호출함으로써 network연결을 종료하고 최종적으로 server도 종료하게 됩니다.
using System;
using System.Net;
using System.Net.Sockets;
using static System.Console;
using System.Text;
namespace client
{
class Program
{
static void Main(string[] args)
{
IPEndPoint serverAddress = new IPEndPoint(IPAddress.Parse("172.27.145.29"), 3000);
IPEndPoint clientAddress = new IPEndPoint(IPAddress.Parse("172.27.144.1"), 3000);
TcpClient client = new TcpClient(clientAddress);
client.Connect(serverAddress);
WriteLine("서버 연결");
byte[] data = System.Text.Encoding.Default.GetBytes(args[0]);
NetworkStream stream = client.GetStream();
stream.Write(data, 0, data.Length);
data = new byte[256];
int bytes = stream.Read(data, 0, data.Length);
string res = Encoding.Default.GetString(data, 0, bytes);
WriteLine(res);
stream.Close();
client.Close();
WriteLine("종료");
}
}
}
참고로 server나 client모두 network 통신을 위해서는 ip와 port가 필요한데 이는 IPEndPoint class를 사용해 처리하고 있습니다.
client에서는 server와의 연결을 TcpClient의 Connect() method를 호출하는 것으로 시작하며 일단 연결이 이루어지면 보내고자 하는 내용의 데이터를 byte로 변환해 Write()메서드로 송신합니다. server에서는 data를 받으면 다시 받은 data를 보내주도록 되어 있으므로 이를 Read() method로 받아 화면에 출력한 뒤 server와의 연결을 종료합니다.
'.NET > C#' 카테고리의 다른 글
[C#] Entity Framework Core - 1. 시작/설정하기 (0) | 2022.06.24 |
---|---|
[C#] 함수(메서드)의 실행과 디버깅및 테스팅 (0) | 2022.05.06 |
[C#] Thread(스레드)와 Task(태스크) (2) | 2021.10.24 |
[C#] 파일과 디렉터리 다루기 (0) | 2021.10.21 |
[C#] dynamic 형식 (0) | 2021.10.21 |