CommandLine Arguments
시뮬 돌릴 대 '옵션만 바꿔서" 재컴팡리 안하게 해주는 장치
코드에 변수 뚫어놓고 -> 실행할 때 --size=128 이런 식으로 값만 밀어버린다.
“CommandLine은 ‘짓고 난 뒤에 다이얼 돌리는 손잡이’.
코드에 AddValue 몇 줄 박아두면,
./waf --run "시나리오 --딜레이=1s --howmany=999" 이렇게 옵션 뿌려 넣어 실험치만 무한 갈아끼울 수 있음 ㅋㅋ 귀찮은 재컴파일은 이제 그만.”
구조 한번 맛봐보자
int main(int argc, char* argv[])
{
/* 0. 디폴트 값 준비 */
uint32_t maxPackets = 1;
std::string delay = "2ms";
uint32_t pktSize = 1024;
double interval = 1.0;
std::string bw = "5Mbps";
/* 1. 파서 선언 + 훅(hook) 연결 */
CommandLine cmd;
cmd.AddValue("howmany", "Number of packets to echo", maxPackets);
cmd.AddValue("delay", "Line Delay", delay);
cmd.AddValue("size", "Packet Size", pktSize);
cmd.AddValue("interval", "Interval", interval);
cmd.AddValue("bw", "BandWidth", bw);
/* 2. 실제 argv 파싱 → 위 변수들에 덮어쓰기 */
cmd.Parse(argc, argv);
/* 3. 이후 코드는 수정된 변수 사용 */
pointToPoint.SetChannelAttribute("Delay", StringValue(delay));
pointToPoint.SetDeviceAttribute ("DataRate",StringValue(bw));
echoClient.SetAttribute("MaxPackets", UintegerValue(maxPackets));
echoClient.SetAttribute("Interval", TimeValue(Seconds(interval)));
echoClient.SetAttribute("PacketSize", UintegerValue(pktSize));
Simulator::Run(); Simulator::Destroy();
}
실행‑예
./waf --run "scratch/myfirst" | 디폴트(1 pkt·2 ms) |
./waf --run "scratch/myfirst --howmany=2 --delay=10ms" | 2개 전송, 링크 지연 10 ms로 변경 |
./waf --run "scratch/myfirst --interval=2 --size=128 --bw=1Mbps" | 2 초 간격·128B 패킷·1 Mbps 링크로 실험 |
로그 보면 딱 송수신 시각·횟수가 바뀌는 걸 확인할 수 있다.
팁과 주의
변수 타입 추적 | uint32_t, double, std::string 전부 자동 파싱 지원. |
설명란(Help) | cmd.AddValue("delay", "Line Delay", delay); 의 두 번째 인자는 --help 찍을 때 표시. |
위치 | cmd.Parse() 전에 링크 지연·앱 속성 세팅 같은 코드 넣으면 안 됨—변수 값이 아직 안 바뀐 상태라서. |
대량 파라미터 | 과제·논문용 스위프 실험은 bash for‑loop로 옵션만 바꿔 수백 번 실행하면 끝 |
High-Level Tracing
“로그는 ‘지금 뭐 하고 있냐’ 실시간 중계고
트레이스(PCAP)는 ‘패킷 하나하나 직캠’ 찍어서 파일로 저장해 두는 거다.
한마디로 ‘흔적 남기기’. 나중에 성능 까거나 버그 잡을 때 100% 필요.”
트레이싱 시스템 – 큰 그림

Trace Source | “일 터지면 바로 실시간 알림 쏘는 센서” | 이벤트 발생 지점 (예: NetDevice가 패킷 전송 끝났을 때 PhyTxEnd) |
Trace Sink | “센서 알림 받아서 로그·그래프 그리는 관제실” | 콜백 함수·파일 라이터 등 |
Helper | “센서랑 관제실 선 연결 자동 배선공” | PcapHelper / AsciiTraceHelper |
Source는 모듈 안에 이미 박혀 있음 (불변).
Sink만 유저가 골라서 ‘꽂는’ 구조. 위 이미지에서 ‘Unchanging’ vs ‘Configurable by user’ 박스가 그 얘기.
하이레벨 트레이싱 (귀차니즘 버전)
EnablePcapAll 한 줄 치면 끝
pointToPoint.EnablePcapAll("firstcap");
- 이름(prefix) 만 넣으면 firstcap-0-0.pcap, firstcap-1-0.pcap … 자동생성
- 어느 NetDevice가 어느 방향으로 보낸 건지 IPX번호로 구분
(0‑0 = 노드0 디바이스0)
“와프(waf) 빌드하고 시뮬만 돌려도, 패킷 ‘직캠’이 ns‑3.29/ 폴더에 떡! 하고 떨어짐.”
# 패킷 찍고
./waf --run "scratch/myfirst --interval=2 --size=128 --howmany=2 --delay=1000ms"
# 바로 해석
tcpdump -nn -tt -r firstcap-0-0.pcap
출력 예
2.000000 IP 10.1.1.1.49153 > 10.1.1.2.9: UDP, length 128
4.000000 IP 10.1.1.1.49153 > 10.1.1.2.9: UDP, length 128
...
- -nn : DNS·포트 이름 해석 끄고 숫자로 뿌려라
- -tt : 타임스탬프 그냥 초(sec) 단위 정수로 줘라
- -r : pcap 읽기 모드
Wireshark? 걍 GUI 버전 tcpdump라 보면 됨. 필터 udp && frame.len==128 딱 치면 원하는 프레임만 추려짐.
Application in ns-3
우리가 그동안 얘를 뭐라고 다뤘냐
현실로 치면 유튜브 켠 크롬 브라우저, 사용자 프로그램(웹 브라우저, ip 등이다), 트래픽을 만드는 주체이고 패킷 만들고(Send) 받는(Recv) 로직 담당. Echo Client, OnOffApp 등 이미 만들어진 놈도 있고, 직접 만들수도 있다
뭐 이렇게 설명을 해왔는데, 좀 더 자세히 들여다보자고 ㅇㅇ
자, 얘는 뭐다? Node 위에서 패킷을 뿜어내고 받아먹는 프로그램이야.
OnOffApplication | OnOffHelper | CBR(constant bit rate) 트래픽을 On/Off 패턴으로 뿌림 | DataRate, PacketSize, OnTime, OffTime |
PacketSink | PacketSinkHelper | 패킷 받고 끝. 로깅용 | Protocol, Local |
UdpEcho | UdpEchoClient/ServerHelper | 클라가 보내면 서버가 그대로 에코 | 클라 MaxPackets‧Interval‧PacketSize, 서버 Port |
UdpClient/Server | UdpClient/ServerHelper | 순수 UDP 송수신 | 클라 Interval‧RemoteAddress‧RemotePort, 서버 PacketWindowSize |
onoffapplication 들여다보자
// 목적지
uint16_t port = 9;
Ipv4Address dst = Ipv4Address("10.1.1.2");
// 헬퍼 생성
OnOffHelper onoff("ns3::UdpSocketFactory",
Address(InetSocketAddress(dst, port)));
// 속성 세팅
onoff.SetAttribute("DataRate", DataRateValue("5Mbps"));
onoff.SetAttribute("PacketSize", UintegerValue(1024));
onoff.SetAttribute("OnTime",
StringValue("ns3::ConstantRandomVariable[Constant=1.0]"));
onoff.SetAttribute("OffTime",
StringValue("ns3::ConstantRandomVariable[Constant=1.0]"));
// 노드0에 설치하고 1~10초 가동
ApplicationContainer apps = onoff.Install(nodes.Get(0));
apps.Start(Seconds(1.0));
apps.Stop (Seconds(10.0));
- OnTime/OffTime 둘 다 1 초 ⇒ 1초 뿜고 1초 쉼
- DataRate × PacketSize = 실측 전송률.
PacketSink
PacketSinkHelper sink("ns3::UdpSocketFactory",
Address(InetSocketAddress(Ipv4Address::GetAny(), port)));
ApplicationContainer snk = sink.Install(nodes.Get(1));
snk.Start(Seconds(1.0));
snk.Stop (Seconds(10.0));
결과는 PacketSink가 stdout으로 “Received N bytes” 찍어줌. 분석 끝.
UdpEcho
// 서버(node1)
UdpEchoServerHelper echoSrv(port);
echoSrv.Install(nodes.Get(1)).Start(Seconds(1));
// 클라이언트(node0)
UdpEchoClientHelper echoCli(dst, port);
echoCli.SetAttribute("MaxPackets", UintegerValue(5));
echoCli.SetAttribute("Interval", TimeValue(Seconds(1)));
echoCli.SetAttribute("PacketSize", UintegerValue(512));
echoCli.Install(nodes.Get(0)).Start(Seconds(2));
- 보내면 바로 에코. RTT 체크용으로 꿀.
UdpClient/Server
// 서버(node1)
UdpServerHelper udpSrv(port);
udpSrv.Install(nodes.Get(1));
// 클라이언트(node0)
UdpClientHelper udpCli(dst, port);
udpCli.SetAttribute("Interval", TimeValue(MicroSeconds(8000))); // 1 Mbps 맞추려면 계산
udpCli.SetAttribute("MaxPackets", UintegerValue(0)); // 0 = 무한
udpCli.SetAttribute("PacketSize", UintegerValue(1024));
udpCli.Install(nodes.Get(0));
- Echo 없음. 서버는 받고 카운트만.
생명주기 API – 켜고 끄는 타이밍
apps.Start(t) / apps.Stop(t) | 컨테이너 몽땅 스케줄 |
SetStartTime(t) / SetStopTime(t) | 개별 객체 수동 세팅 |
StartApplication() / StopApplication() | 프레임워크가 자동 호출 → 여기서 소켓 열고 닫음 |
아무튼 정리하자면,,,
- NodeContainer nodes.Create(…)
- PointToPoint/Csma 등으로 NetDevice + Channel 설치
- InternetStackHelper → Ipv4AddressHelper
- Application Helper 설치 + Start/Stop
예시를 들어보자
노드 2개 → P2P 5 Mbps / 2 ms 링크 →
① UdpEcho 데모(핑퐁)
② OnOffApplication 데모(CBR 뿜뿜)
슬라이드 그림에 나오는 10.1.1.0/24 세그먼트가 전부다.
코드 두 개(week4_ex2_udp_echo.cc, week4_ex2_onoff_app.cc)를 순서대로 보자.
A. week4_ex2_udp_echo.cc – 핑퐁 맛보기
1단계 ‑ 로깅 옵션 먹이기
bool verbose = true; // 기본값 ON
CommandLine cmd;
cmd.AddValue("verbose", "log?", verbose);
cmd.Parse(argc, argv);
if (verbose) {
LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
}
- ./waf --run "… --verbose=0" 하면 로그 잠궈버릴 수도 있다.
2단계 ‑ 노드 2개 뚝딱
NodeContainer p2pNodes;
p2pNodes.Create(2);
3단계 ‑ 링크&NIC 장착
PointToPointHelper p2p;
p2p.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
p2p.SetChannelAttribute("Delay", StringValue ("2ms"));
NetDeviceContainer p2pDevs = p2p.Install(p2pNodes);
- DeviceAttribute = NIC 속도, ChannelAttribute = “가상 UTP” 지연.
4단계 ‑ IP 스택 + 주소
InternetStackHelper stack;
stack.Install(p2pNodes);
Ipv4AddressHelper addr;
addr.SetBase("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer ifs = addr.Assign(p2pDevs);
- ifs.GetAddress(0) → 10.1.1.1, ifs.GetAddress(1) → 10.1.1.2.
5단계 ‑ Echo 서버(node1) 세팅
UdpEchoServerHelper echoServer(9); // 포트 9 (discard)
ApplicationContainer sApps = echoServer.Install(p2pNodes.Get(1));
sApps.Start(Seconds(1));
sApps.Stop (Seconds(10));
6단계 ‑ Echo 클라이언트(node0)
UdpEchoClientHelper echoClient(ifs.GetAddress(1), 9);
echoClient.SetAttribute("MaxPackets", UintegerValue(100));
echoClient.SetAttribute("Interval", TimeValue(Seconds(1)));
echoClient.SetAttribute("PacketSize", UintegerValue(1024));
ApplicationContainer cApps = echoClient.Install(p2pNodes.Get(0));
cApps.Start(Seconds(2));
cApps.Stop (Seconds(10));
- 2초부터 10초까지 1초 간격으로 100개까지만 쏨.
7단계 ‑ 패킷 캡처
p2p.EnablePcapAll("second"); // second-0-0.pcap / second-1-0.pcap
8단계 ‑ 시뮬레이터 스타트
Simulator::Run();
Simulator::Destroy();
뇌리에 박기 – UDP 에코 흐름
클라(node0) 1024B → 서버(node1) 도착 → 바로 되돌려 보냄 → node0 수신, 로그 찍힘.
B. week4_ex2_onoff_app.cc – CBR 발사기
슬라이드 24–25에 해당.
1~4단계는 똑같음 (노드·링크·IP까지 동일)
5단계 ‑ OnOffApplication 생성
uint16_t port = 9;
OnOffHelper onoff("ns3::UdpSocketFactory",
Address(InetSocketAddress(Ipv4Address("10.1.1.2"), port)));
onoff.SetAttribute("OnTime",
StringValue("ns3::ConstantRandomVariable[Constant=1]"));
onoff.SetAttribute("OffTime",
StringValue("ns3::ConstantRandomVariable[Constant=1]"));
onoff.SetAttribute("DataRate", DataRateValue("5Mbps")); // CBR 속도
ApplicationContainer app = onoff.Install(terminals.Get(0)); // node0
app.Start(Seconds(1));
app.Stop (Seconds(10));
- 1초 On / 1초 Off 반복.
- DataRate 5 Mbps, PacketSize(디폴트 512B) → 초당 약 1 k패킷쯤.
6단계 ‑ PacketSink(node1)
PacketSinkHelper sink("ns3::UdpSocketFactory",
Address(InetSocketAddress(Ipv4Address::GetAny(), port)));
sink.Install(terminals.Get(1)).Start(Seconds(1));
7단계 ‑ 15초에 시뮬 종료
Simulator::Stop(Seconds(15)); // 몇 초 더 넉넉히
Simulator::Run();
Simulator::Destroy();
결과
node1 PacketSink 가 “Received xxx bytes” 스팸처럼 찍어준다.
PCAP 안 켰으니 필요하면 p2p.EnablePcapAll(...) 추가.
핵심만 머리에 박아!
1 | nodes.Create(2); |
2 | PointToPointHelper 로 속도/딜레이 세팅 → Install() |
3 | InternetStackHelper + Ipv4AddressHelper |
4 | App Helper 붙이고 Start/Stop 시간만 지정 |
5 | 필요하면 EnablePcapAll() 딱 한 줄 |
최종정리
1. Command‑Line Args (CommandLine cmd; … AddValue) |
‑ C++ 소스 뜯어 고치지 말고, 실행 시 옵션으로 파라미터 집어넣어라 → 시뮬 돌릴 때 ./waf --run "myfirst --howmany=2 --delay=10ms" 같은 식 |
2. Tracing System & PCAP | ‑ EnablePcapAll() 한 줄이면 패킷 캡처(.pcap) 자동 생성 ‑ tcpdump ‑nn -tt -r file.pcap or Wireshark로 바로 확인 |
3. ns‑3 Application 카달로그 | ‑ 이미 구현된 4대 천왕: 1) OnOffApplication (CBR 발사·휴식) 2) PacketSink (받고 끝) 3) UdpEcho (Client/Server) (핑퐁) 4) UdpClient / UdpServer (클라→서버 단방향) |
4. Helper + Attribute 패턴 | ‑ 무조건 *_Helper helper; → helper.SetAttribute("Foo", ...) → helper.Install(node) ‑ Attributes= 데이터레이트, 패킷사이즈, Interval… 실험값만 쓱 갈아끼우면 끝 |
5. Application 수명주기 | ‑ Start(Time) / Stop(Time) = 이벤트 스케줄링 ‑ 실행 중간에 Simulator::Run() 한방이면 타임라인대로 다 처리 |
6. Example 2 코드 (Echo & OnOff) |
‑ P2P 링크 만들기 → IP 부여 → App 올리기 3‑Step 템플릿 시연 ‑ Echo 예제: 끊임없이 핑·퐁 확인 ‑ OnOff 예제: 1 초 On / 1 초 Off CBR 패턴 보여주기 |
'프로그램 공부 > 네트워크프로젝트' 카테고리의 다른 글
네트워크 프로젝트 5주차 (0) | 2025.04.22 |
---|---|
네트워크 프로젝트 3주차 (0) | 2025.04.21 |
네트워크 프로젝트 1주차 (0) | 2025.04.21 |