Socket_2
Socket_2: DNS 서버 시뮬레이터
프로그램 설명
이 프로그램은 도메인 이름과 IP 주소 간의 매핑 정보를 처리하는 간단 DNS(Domain Name System) 서버 시뮬레이터이다.
실제 DNS 서버처럼, 클라이언트는 도메인 이름을 서버에 요청하고, 서버는 그에 해당하는 IP 주소를 반환한다. 또한 클라이언트가 새로운 도메인-IP 매핑 정보를 등록할 수도 있으며, 이 정보는 서버의 데이터베이스(SQLite)에 저장된다.
소스 프로그램
[1] dns_server_db.py
– 서버 코드 (SQLite DB 사용)
import socket
import sqlite3
# 데이터베이스 연결 및 테이블 생성
conn = sqlite3.connect("dns.db", check_same_thread=False)
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS dns_table (
domain TEXT PRIMARY KEY,
ip TEXT
)
""")
conn.commit()
HOST = '127.0.0.1'
PORT = 9999
# TCP 서버 소켓 설정
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((HOST, PORT))
server_socket.listen(1)
print(f"[DNS 서버] {HOST}:{PORT} 에서 실행 중...")
while True:
client_socket, addr = server_socket.accept()
print(f"[접속] 클라이언트: {addr}")
while True:
try:
data = client_socket.recv(1024).decode()
if not data:
break
tokens = data.strip().split()
if tokens[0] == 'r': # 조회
if len(tokens) != 2:
response = "[ERROR] r 명령어 형식: r 도메인"
else:
domain = tokens[1]
cursor.execute("SELECT ip FROM dns_table WHERE domain = ?", (domain,))
row = cursor.fetchone()
if row:
response = f"{domain} → {row[0]}"
else:
response = f"[ERROR] {domain} not found."
elif tokens[0] == 'w': # 등록
if len(tokens) != 3:
response = "[ERROR] w 명령어 형식: w 도메인 IP주소"
else:
domain, ip = tokens[1], tokens[2]
cursor.execute("INSERT OR REPLACE INTO dns_table (domain, ip) VALUES (?, ?)", (domain, ip))
conn.commit()
response = f"[OK] {domain} → {ip} 등록 완료."
else:
response = "[ERROR] 알 수 없는 명령어입니다. r 또는 w 사용."
client_socket.sendall(response.encode())
except ConnectionResetError:
break
client_socket.close()
print(f"[종료] 클라이언트: {addr}")
[2] dns_client.py
– 클라이언트 코드
import socket
HOST = '127.0.0.1'
PORT = 9999
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as client_socket:
client_socket.connect((HOST, PORT))
print("[클라이언트] DNS 서버에 연결되었습니다. (종료하려면 'exit' 입력)")
while True:
cmd = input("명령 입력 (예: r google.com / w mysite.com 192.168.0.10): ").strip()
if cmd == 'exit':
break
client_socket.sendall(cmd.encode())
data = client_socket.recv(1024).decode()
print(f"[서버 응답] {data}")
실행 방법 요약
- 두 파일을 같은 폴더에 저장
- 터미널 2개 실행
클라이언트에서 명령 입력 예시:
w example.com 8.8.8.8
r example.com
다른 하나는 클라이언트 실행:
python dns_client.py
하나는 서버 실행:
python dns_server_db.py
DB에 저장되는 DNS 서버 구축 완료.
dns_server_db.py
코드 설명
이 코드는 클라이언트로부터 도메인 조회(r
) 또는 등록(w
) 요청을 받아 처리하고, 도메인-IP 매핑 정보를 SQLite 데이터베이스에 저장하는 DNS 서버 역할을 한다.
주요 구성
1. SQLite 연결 및 테이블 생성
conn = sqlite3.connect("dns.db", check_same_thread=False)
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS dns_table (
domain TEXT PRIMARY KEY,
ip TEXT
)
""")
dns.db
라는 이름의 데이터베이스 파일을 생성 (또는 연결)dns_table
이라는 테이블을 만들고domain
과ip
저장domain
은 중복 불가능한 기본 키(Primary Key)
2. 서버 소켓 생성 및 바인딩
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((HOST, PORT))
server_socket.listen(1)
- TCP 통신용 소켓 생성
127.0.0.1
(로컬호스트)와 포트9999
에 바인딩- 클라이언트 접속 대기 상태로 전환
3. 클라이언트 접속 수락 및 통신 처리
client_socket, addr = server_socket.accept()
- 클라이언트가 접속하면 연결 수락하고
client_socket
생성
4. 명령어 처리
data = client_socket.recv(1024).decode()
tokens = data.strip().split()
- 클라이언트가 보낸 메시지를 받아서 공백 기준으로 분해
➤ r 도메인
요청
cursor.execute("SELECT ip FROM dns_table WHERE domain = ?", (domain,))
- 데이터베이스에서 해당 도메인을 조회
- 있으면 IP 응답, 없으면 에러 메시지
➤ w 도메인 IP주소
요청
cursor.execute("INSERT OR REPLACE INTO dns_table (domain, ip) VALUES (?, ?)", (domain, ip))
- 도메인을 등록하거나 기존 것을 업데이트
- DB에 즉시 반영:
conn.commit()
5. 응답 전송
client_socket.sendall(response.encode())
- 서버가 처리 결과를 클라이언트에게 문자열 형태로 전송
6. 연결 종료 처리
client_socket.close()
- 통신 종료 시 소켓 닫기
dns_client.py
코드 설명
이 코드는 사용자로부터 명령어를 입력받아 서버에 전송하고, 응답 결과를 출력하는 클라이언트 역할을 한다.
주요 구성
1. 서버에 접속
client_socket.connect((HOST, PORT))
- 서버(IP
127.0.0.1
, 포트9999
)에 연결
2. 명령어 입력 및 전송
cmd = input("명령 입력 ...")
client_socket.sendall(cmd.encode())
- 사용자 입력을 받아 서버로 전송 (
r 도메인
,w 도메인 IP
)
3. 응답 수신 및 출력
data = client_socket.recv(1024).decode()
print(f"[서버 응답] {data}")
- 서버로부터 받은 메시지를 화면에 출력
4. 종료 명령
if cmd == 'exit':
break
- 사용자가
exit
를 입력하면 프로그램 종료
출력 내용 + 입력 내용
서버 측 출력:

클라이언트 측 출력:

DB 확인:
