오늘은 OMNeT++ 실행시키고 아래의 OMNeT++ 기술 문서의 TicToc 예제를 한번 해볼 것임
https://docs.omnetpp.org/tutorials/tictoc/part1/
OMNeT++을 실행해주면 다음과 같은 IDE가 나오게 됨
OMNeT++ Proejct를 눌러주고

프로젝트 명은 tictoc으로 했습니다.
하고 나서, 다음 화면에 exmaples 디렉토리가 있는데 거기 안에 tictoc_examples가 존재해서 그거 클릭하고 Finish!

먼저 왼쪽 Project Explorer에 tictoc이 존재하니 잘 들어와진 거고..
이제 이런 화면이 나왔다는 뜻은 "워크스페이스가 비었는데, 예제 가져올래?" 라고 묻는 거임
- 위: Install INET Framework (not recommended, use opp_env instead) -> INET 설치할래??? 근데.. omnetpp가 opp_env로 설치된 것을 감지했으니까, inet이 필요하면 opp_env install inet-latest로 깔고, 그 다음 IDE로 import해..! (알겠습니다 하고 그냥 아래 버튼 누르면 된다)
- 아래: Import omnetpp programming examples -> omnetpp 처음이면 이거 선택해. omnetpp에 딸린 examples를 워크스페이스로 가져올거야.

왼쪽 보면 examples 다 가져온 것을 확인할 수 있다. 이제 왼쪽에서 우리가 실행할 tictoc 부분을 확인해보자.

src/ (소스 = 동작 및 구조를 정의)
- Txc.ned: 모듈의 구조(NED): 게이트가 어떻게 생겼나
- Txc.cc / Txc.h: 모듈의 동작(C++): handleMessage 여기서 함
simulations/ (실제 돌릴 것)
- Tictoc.ned: 어느 모듈을 어떻게 연결했나
- omnetpp.ini: 어떤 네트워크를 얼마나 돌릴까
Makefile, Includes, run (빌드 및 실행 보조)
그러면 이제 가장 단순한 것부터 읽어보도록 하자. 순서는 아래와 같이 갈거임
(1) Txc.ned (2) Tictoc.ned (3) Txc.cc (4) omnetpp.ini
Txc.ned

package tictoc;
// 패키지 선언
// 단순히 이 모듈은 tictoc 패키지 소속이라는 것을 선언한 정도로 알면 됨
//
// Immediately sends out any message it receives. It can optionally generate
// a message at the beginning of the simulation, to bootstrap the process.
//
simple Txc
// simple이라는 뜻은 Simple module이라는 것
// 만약 module이었다면 그것은 compound module이고, 다른 모듈을 담는 상자임
// 이 Txc는 Txc.cc에 실제 어떤 행동을 하는지가 들어있음 (Txc = Transmitter/something의 약자)
{
parameters:
bool sendInitialMessage = default(false);
// 파라미터 선언 - omnetpp.ini에서 값을 바꿔 끼울 수 있음
gates:
input in;
output out;
// 게이트 선언 - 모듈은 게이트를 통해서만 바깥과 통신한다!
}
이 NED를 한 줄로 요약해보자면 다음과 같음.
"Txc는 단순 모듈이다. 손잡이 하나(sendInitialMessage, 켜면 시동을 건다)를 갖고, 입구(in)와 출구(out) 게이트가 있다. 받으면 되쏜다(동작은 Txc.cc에)."
이 파일엔 Txc가 자기가 어떻게 생겼는지 선언만 하지 누구랑 연결되는지는 모름. 그 연결은 TicToc.ned에서 정해지게 됨.
그러면 이제 Tictoc.ned를 확인해보자

tic과 toc이 서로 연결된 것을 확인할 수 있음. 그리고 toc 위에 초록색 표식이 있는데, ini에서 toc이 시동 거는 쪽으로 설정됐다는 신호임.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see http://www.gnu.org/licenses/.
//
package tictoc.simulations;
// tictoc.ned는 tictoc.simulations pkg안에 들어있음
import tictoc.Txc;
// tictoc 패키지 내부의 Txc를 가져오겠다
//
// Two instances (tic and toc) of Txc connected.
//
network Tictoc
// simple = 동작 코드를 가진 앞 모듈
// network = 최상위 compound module. 다른 모듈들을 담아 연결만 하는 상자임. 자기 동작 코드는 따로 없음 (handle message)
{
@display("bgb=367,338");
submodules:
tic: Txc;
toc: Txc {
@display("p=239,61");
}
// tic과 toc은 같은 타입(Txc)의 서로 다른 인스턴스
connections:
// tic의 out 게이트는 toc의 in gate와 연결돼있고
// toc out은 tic의 in과 연결돼있다.
// delay를 줌으로 이 선을 건너는 데 100ms propagation delay가 생기는 것을 선언
tic.out --> { delay = 100ms; } --> toc.in;
tic.in <-- { delay = 100ms; } <-- toc.out;
}
질문: 이 "100ms 지연"은 DES 커널 입장에서 보면 뭘 의미할까?
답: 다음 이벤트로 jump할건데 그 시간이 100ms
이제 Txc.cc
#include "Txc.h"
namespace tictoc {
Define_Module(Txc); // 이 C++ 클래스 Txc가, "NED에서 simple Txc로 선언한 그 모듈의 동작 구현이다" 선언
// 기존의 simple module은 NED + C++과 한 쌍. 이 매크로가 연결고리가 되는 것임
void Txc::initialize() // initialize/handleMessage/finish 중 첫 번째. 시뮬레이션 시작 때 각 모듈마다 딱 한번 불림
{
if (par("sendInitialMessage").boolValue()) // NED에서 선언하고 ini에서 값을 줬던 그게 true인 모듈만 안으로 들어가서
{
cMessage *msg = new cMessage("tictocMsg"); // 새로운 메시지 객체를 하나 만들고
send(msg, "out"); // out 게이트로 보내는 것임
}
}
void Txc::handleMessage(cMessage *msg)
{
// just send back the message we received
send(msg, "out");
}
}; // namespace
그래서 이 TicToc을 보면 어떠한 과정으로 진행되는 것이냐?
- toc이 initialize()에서 첫 msg를 tic에게 던짐 (100ms 뒤 도착)
- 100ms 후, tic의 handleMessage 호출 -> 받은 걸 그대로 toc에게 되쏨
- 100ms 후, toc의 handleMessage 호출 -> 받은 걸 그대로 tic에게 되쏨
- 무한반복
그러면 이제 simulations/omnetpp.ini를 한번 봐보자.

Form에는 뭐가 되게 많은데, Source는 반대로 되게 짧다.
[General] // [General]은 기본 구역. 나중에는 [Config PureAloha1]처럼 여러 실험 설정을 한 ini에 담을 수 있다
network = Tictoc // 어떤 network를 세울까? -> Tictoc.ned를 지목하는 것
// 이게 있어야 커널이 아 tic이랑 toc 만들고 100ms 링크로 연결해야겠네 알게됨
cpu-time-limit = 60s
// 실제 CPU 시간으로 60초 돌면 멈춰러 (이건 실제 시간)
// tictoc은 무한 루프기 때문에 그냥 1분 돌면 멈추라는 뜻임
#debug-on-errors = true
// 에러 나면 디버거 붙어라 -> 근데 지금 주석 달려있어서 꺼져있음
**.tic.sendInitialMessage = true
// tic의 sendInitialMessage를 (Txc.ned에서 기본값 false였던 것을) true로 override
// toc은 기본값 false라 안 던짐.
과정 정리 한 번만 더
omnetpp.ini : Tictoc 네트워크를 세워라. tic이 첫 msg를 보내도록 해라.
Tictoc.ned : tic-toc 두 Txc를 100ms 링크로 양방향 연결한 network를 만든다
Txc.ned : 각 Txc의 in/out 게이트와 sendInitialMessage 손잡이를 가진 simple module을 생성
Txc.cc : tic은 initialize()에서 첫 공 던지고, 받는 쪽은 handleMessage()에서 다시 되쏨
이제 실제로 돌려봐야지
simulations/omnetpp.ini를 우클릭해서 Run하면 된다.
실행시키면 이렇게 나오게 됨

가장 맨 윗 줄은 FEL(미래 이벤트 목록)의 맨 위 항목을 보여주는 것임
Next: 다음에 처리될 이벤트는 tictocMsgㅡTxc.cc initialize()에서 tic이 new cMessage로 만든 것.
In: 이벤트가 도착할 모듈은 toc.
At: 0.1s 도착 시간은 가상 시간 0.1초 (= 100ms).
좌측 상단 모듈 트리는 NED로 읽은 객체 모델이 실제로 인스턴스화된 모습임
- Tictoc (Tictoc) id = 1 : 최상위 network
- tic (Txc) id = 2 & toc (Txc) id = 3 : 둘 타입은 Txc인데 인스턴스가 다르니까 id도 다른 것임
- simulation.scheduled-events : 이게 FEL. 펼치면 예약된 이벤트 목록들을 볼 수 있음

좀 더 deep하게 들어가볼까.. 해체쇼는 언젠가 해야해


tic만 먼저 까봤는데, in이랑 out cGate 두 객체를 볼 수 있음. (c = OMNeT++ 클래스 접두사) Txc.ned에 이전에 input in; output out;이라고 선언해놓은 거 기억하려나
그리고 그 옆에 -->와 <--가 존재하는데 connection도 보여주는 것임. tic의 out gate는 toc의 in gate로 향한다.
channel delay = 100ms. 우리가 선언해줬던 것처럼!
가장 마지막에 simulation.scheduled-events (cEventHeap) 이것이 바로 FEL (Future Event List)
클래스 이름이 cEventHeap -> FEL은 priority queue. heap이 바로 그 자료구조임.