2025. 4. 11. 17:52ใDevelopment๐ฉ๐ป๐ฆณ/Communication
๋จ์ํ ๋์ ์ดํด๋ฟ๋ง ์๋๋ผ, ์ค๋ฅ ์ฒ๋ฆฌ ํ๋ฆ, ์ ์ญ ๋ณ์ ํ์ฉ, Winsock ํ์ฅ ํจ์ ์ ์ฉ๋ฒ๊น์ง ์ค๋ฌด์ ์ธ ์ธก๋ฉด์ ๊ณ ๋ คํด ์ ๋ฆฌํ๋ค.
โ ์ฐ์ต๋ฌธ์ 05-B: ์ฌ์ฉ์ ์ ์ ํจ์์ ์ค๋ฅ ์ฒ๋ฆฌ
๐ง ์๊ตฌ ์ฌํญ ์์ฝ
- f(int x) ํจ์๋ x๊ฐ ์์๋ฉด ์คํจ, ๊ทธ๋ ์ง ์์ผ๋ฉด ์ฑ๊ณต
- ์คํจ ์ errno ์ ์ญ ๋ณ์์ EINVAL ์ค์
- ๋ฆฌํด ๊ฐ์ ์ฑ๊ณต ์ 0, ์คํจ ์ 1
๐ ๊ตฌํ ์ฝ๋ ์์
c
๋ณต์ฌํธ์ง
#include <stdio.h>
#include <errno.h> // errno, EINVAL
#include <stdlib.h> // exit()
void err_quit(const char* msg) {
perror(msg);
exit(1);
}
int f(int x) {
if (x >= 0) {
errno = 0;
return 0;
} else {
errno = EINVAL; // Invalid argument
return -1;
}
}
int main() {
int retval = f(-100); // ์คํจ ์๋
if (retval < 0)
err_quit("f()");
return 0;
}
๐ก ์คํ ๊ฒฐ๊ณผ ์์
plaintext
๋ณต์ฌํธ์ง
f(): Invalid argument
errno๋ C ํ์ค์ ์ ์ญ ์ค๋ฅ ์ฝ๋ ๋ณ์์ด๋ฉฐ, ์์คํ ํธ์ถ ์ค๋ฅ ์ธ์๋ ์ฌ์ฉ์ ์ ์ ํจ์์์ ๋์ผํ ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌ ๊ฐ๋ฅํ๋ค.
โ ์ฐ์ต๋ฌธ์ 06: WSASocket()์ผ๋ก TCP / UDP ์์ผ ์์ฑ
๐ ๊ฐ์
**WSASocket()**์ **socket()**๊ณผ ์ ์ฌํ์ง๋ง ํ์ฅ ์ต์ , ์ค๋ฒ๋ฉ IO, ํ๋๊ทธ ์ง์ ์ด ๊ฐ๋ฅํ Winsock ๊ณ ๊ธ ํจ์๋ค.
๐ง ๊ธฐ๋ณธ ์ฌ์ฉ ํ์
c
๋ณต์ฌํธ์ง
SOCKET WSASocket(
int af, // ์ฃผ์ ์ฒด๊ณ (์: AF_INET)
int type, // ์์ผ ํ์
(์: SOCK_STREAM)
int protocol, // ํ๋กํ ์ฝ (์: IPPROTO_TCP)
LPWSAPROTOCOL_INFO lpProtocolInfo,
GROUP g,
DWORD dwFlags // ์ต์
ํ๋๊ทธ
);
๐ TCP/UDP ์์ผ ์์ฑ ์์ ์ฝ๋
c
๋ณต์ฌํธ์ง
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32")
void err_quit(const char* msg) {
fprintf(stderr, "[์ค๋ฅ] %s: %d\\n", msg, WSAGetLastError());
exit(1);
}
int main() {
WSADATA wsa;
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
err_quit("WSAStartup()");
// TCP ์์ผ
SOCKET tcp_sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
if (tcp_sock == INVALID_SOCKET)
err_quit("WSASocket() - TCP");
// UDP ์์ผ
SOCKET udp_sock = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, 0);
if (udp_sock == INVALID_SOCKET)
err_quit("WSASocket() - UDP");
printf("TCP ์์ผ: %d\\n", (int)tcp_sock);
printf("UDP ์์ผ: %d\\n", (int)udp_sock);
closesocket(tcp_sock);
closesocket(udp_sock);
WSACleanup();
return 0;
}
โ ํต์ฌ ์ฐจ์ด์ ์์ฝ: socket() vs WSASocket()
ํญ๋ชฉ socket() WSASocket()
๊ธฐ๋ณธ ์ฉ๋ | ๋จ์ ์์ผ ์์ฑ | ๊ณ ๊ธ ๊ธฐ๋ฅ ์ค์ ์ด ํ์ํ ์์ผ ์์ฑ |
ํ์ฅ ์ต์ | ๋ถ๊ฐ | dwFlags ํ๋๊ทธ๋ก ์ค์ ๊ฐ๋ฅ (์: ์ค๋ฒ๋ฉ) |
ํ์ฉ ์ํฉ | ๋จ์ ํต์ ํ๋ก๊ทธ๋จ | ๊ณ ์ฑ๋ฅ ์๋ฒ, Overlapped I/O, QoS ๋ฑ ํ์์ |
์ด ์น์ ์์๋ ๋คํธ์ํฌ ํ๋ก๊ทธ๋๋ฐ์์ ๊ฐ์ฅ ์ค์ํ ๊ธฐ๋ฐ ์ค ํ๋์ธ "์ค๋ฅ ์ฒ๋ฆฌ(Error Handling)" ๊ฐ๋ ์ ๋ค๋ฃฌ๋ค. ํนํ ์์ผ ํจ์์ ์คํจ ๊ฐ๋ฅ์ฑ์ด ๋์ ๋งํผ, ์๋์ฐ/๋ฆฌ๋ ์ค ํ๊ฒฝ์์ ์ค๋ฅ๋ฅผ ์ ํํ ํ์งํ๊ณ , ์ฌ์ฉ์์๊ฒ ๋ช ํํ ์ ๋ฌํ๋ ๋ก์ง์ ์ค๋ฌด์์ ๋งค์ฐ ์ค์ํ๋ค.
โ Chapter 02 - 01: ์ค๋ฅ ์ฒ๋ฆฌ ํต์ฌ ์ ๋ฆฌ
๐ ๋คํธ์ํฌ ํ๋ก๊ทธ๋๋ฐ์์ ์ค๋ฅ ์ฒ๋ฆฌ๊ฐ ์ค์ํ ์ด์
- ๋คํธ์ํฌ๋ ์์ธก ๋ถ๊ฐ๋ฅํ ์ธ๋ถ ํ๊ฒฝ์ ์์กด (์ผ์ด๋ธ, ๋ผ์ฐํฐ, ํฌํธ, ๋ฐฉํ๋ฒฝ ๋ฑ)
- ํจ์ ํธ์ถ์ด ์คํจํ ๊ฐ๋ฅ์ฑ์ด ๋๊ธฐ ๋๋ฌธ์ ๋ชจ๋ ์ฃผ์ ์์ผ ํจ์๋ ๋ฐ๋์ ์ค๋ฅ ์ฒดํฌ ํ์
- ์ค๋ฅ ๋ฐ์ ์, ์ฝ๋๋ก๋ ์์ธ๋ง ํ์ธํ ์ ์์ผ๋ฏ๋ก → ์ฌ์ฉ์๋ ๊ฐ๋ฐ์๊ฐ ์ดํดํ ์ ์๋ ๋ฉ์์ง๋ก ์ถ๋ ฅ ํ์
โ ์์ผ ํจ์ ์ค๋ฅ ์ฒ๋ฆฌ ์ ํ (3๊ฐ์ง)
์ ํ ๋ฒํธ ์ค๋ช ์์
โ ์ค๋ฅ ์ฒ๋ฆฌ ํ์ ์์ | ๋ฆฌํด๊ฐ์ด ์๊ฑฐ๋ ์คํจ ๊ฐ๋ฅ์ฑ ์์ | closesocket() ๋ฑ ์ผ๋ถ ํจ์ |
โก ๋ฆฌํด๊ฐ ์์ฒด๊ฐ ์ค๋ฅ ์ ๋ณด ํฌํจ | ์คํจ ์ 0 ๋๋ ์์ ๋ฑ์ผ๋ก ๋ฆฌํด | WSAStartup() |
โข ๋ฆฌํด๊ฐ๊ณผ ์ค๋ฅ ์ฝ๋ ๋ถ๋ฆฌ | ์คํจ ํ์ธ ํ ์ค๋ฅ ์ฝ๋ ํจ์ ํธ์ถ | ๋๋ถ๋ถ์ ์์ผ ํจ์ (socket(), bind() ๋ฑ) |
์ฃผ๋ก ์ฌ์ฉํ๋ ๋ฐฉ์์ โข๋ฒ, ์ฆ "๋ฆฌํด๊ฐ ํ์ธ ํ → ์ค๋ฅ ์ฝ๋ ํจ์ ํธ์ถ"์ด๋ค.
โ 1. ์๋์ฐ ์์ผ ์ค๋ฅ ์ฒ๋ฆฌ ๋ฐฉ์
๐ ๋ํ ํจ์: WSAGetLastError()
- ๋๋ถ๋ถ์ ์์ผ ํจ์๋ ์คํจ ์ INVALID_SOCKET, SOCKET_ERROR ๋ฑ์ ๊ฐ์ ๋ฆฌํด
- ๊ตฌ์ฒด์ ์ธ ์ค๋ฅ๋ **WSAGetLastError()**๋ฅผ ํตํด ํ์ธ
cpp
๋ณต์ฌํธ์ง
#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32")
int main() {
WSADATA wsa;
int result = WSAStartup(MAKEWORD(2, 2), &wsa);
if (result != 0) {
printf("WSAStartup ์คํจ: ์ฝ๋ %d\\n", result);
return 1;
}
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET) {
int errCode = WSAGetLastError();
printf("์์ผ ์์ฑ ์คํจ: ์ฝ๋ %d\\n", errCode);
}
WSACleanup();
return 0;
}
๐ ์ค๋ฅ ๋ฉ์์ง ์ถ๋ ฅ ํจ์ (์ ํ ์ ์ฉ)
์๋์ฐ์์๋ ์ค๋ฅ ์ฝ๋์ ๋ฐ๋ฅธ ์์คํ ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํ๋ ค๋ฉด **FormatMessage()**๋ฅผ ์ฌ์ฉํ ์ ์์:
cpp
๋ณต์ฌํธ์ง
#include <windows.h>
void print_error_message(DWORD errCode) {
LPVOID msg;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, errCode, 0, (LPTSTR)&msg, 0, NULL);
printf("์ค๋ฅ ๋ฉ์์ง: %s\\n", (char*)msg);
LocalFree(msg);
}
โ ์์ฝ ํ๋ฆ
plaintext
๋ณต์ฌํธ์ง
[์์ผ ํจ์ ํธ์ถ]
↓
[๋ฆฌํด๊ฐ์ผ๋ก ์คํจ ์ฌ๋ถ ํ์ธ]
↓
[WSAGetLastError() ํธ์ถ]
↓
[์ค๋ฅ ์ฝ๋ ์ถ๋ ฅ ๋๋ ๋ฉ์์ง ๋ณํ]
๐ ์ค๋ฅ ์ฝ๋ ์์
์ฝ๋ ์๋ฏธ
10013 | ๊ถํ ์์ (Access denied) |
10048 | ์ฃผ์ ์ด๋ฏธ ์ฌ์ฉ ์ค (Address already in use) |
10061 | ๋์ ์ฐ๊ฒฐ ๊ฑฐ๋ถ (Connection refused) |
10060 | ์ฐ๊ฒฐ ์๊ฐ ์ด๊ณผ (Connection timed out) |
์ ์ฒด ์ฝ๋ ๋ชฉ๋ก์ MSDN์ด๋ WinError.h์์ ํ์ธ ๊ฐ๋ฅ
์๋๋ Chapter 02์ ์ฃผ์ ๋ด์ฉ์ ๊ฐ๊ฒฐํ๊ฒ ์ ๋ฆฌํ ์์ฝ๋ณธ์ด๋ค. ํต์ฌ ํจ์์ ๊ฐ๋ ์ ํ๋ซํผ ๋ณ ์ฐจ์ด์ ํจ๊ป ๊ตฌ์กฐ์ ์ผ๋ก ์ ๋ฆฌํด๋์์ผ๋, ์์ผ ํ๋ก๊ทธ๋๋ฐ์ ์ด๊ธฐ ๋จ๊ณ์์ ์ค์ ์ ์ฉ์ ์ํ ๋น ๋ฅธ ์ฐธ์กฐ์ฉ์ผ๋ก ํ์ฉํ๊ธฐ ์ข๋ค.
โ Chapter 02 ์์ฝ: ์์ผ ์์ํ๊ธฐ
โ 01. ์ค๋ฅ ์ฒ๋ฆฌ
ํญ๋ชฉ Windows Linux / POSIX
์ค๋ฅ ์ฝ๋ ์ป๊ธฐ | WSAGetLastError() | ์ ์ญ ๋ณ์ errno |
์ค๋ฅ ๋ฉ์์ง ์ป๊ธฐ | FormatMessage() | strerror(errno) ๋๋ perror() |
๋ชจ๋ ์ฃผ์ ์์ผ ํจ์ (socket(), bind(), connect() ๋ฑ)๋ ์คํจ ์ ์ค๋ฅ ์ฝ๋ ๋ฐํ ํ์
โ 02. ์์ ์ด๊ธฐํ์ ์ข ๋ฃ (Windows ํ์ )
ํจ์ ์ค๋ช
WSAStartup() | ์์ผ ์ฌ์ฉ์ ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ด๊ธฐํ (Winsock 2.x ์ฌ์ฉ) |
WSACleanup() | ์์ผ ์ฌ์ฉ ์ข ๋ฃ, ๋ฆฌ์์ค ๋ฐํ |
โ WSAStartup()์ ๋ฐ๋์ closesocket() ํ WSACleanup()์ผ๋ก ์ ๋ฆฌํด์ผ ํจ
โ 03. ์์ผ ์์ฑ
ํจ์ ์ค๋ช
socket() | ํต์ ์ฉ ์์ผ ์์ฑ, ๋ด๋ถ ๋ฆฌ์์ค๋ฅผ ํ ๋นํ๊ณ ํธ๋ค(SOCKET) ๋ฆฌํด |
๐ TCP/UDP ์ค์ ์กฐํฉ ์์
ํ๋กํ ์ฝ ์ฃผ์ ์ฒด๊ณ (af) ์์ผ ํ์ (type) ํ๋กํ ์ฝ (protocol)
TCP | AF_INET, AF_INET6 | SOCK_STREAM | 0 |
UDP | AF_INET, AF_INET6 | SOCK_DGRAM | 0 |
protocol = 0์ด๋ฉด type์ ๋ฐ๋ผ ์๋ ์ง์ (TCP: IPPROTO_TCP, UDP: IPPROTO_UDP)
โ 04. ์์ผ ๋ซ๊ธฐ
ํ๋ซํผ ํจ์ ๋ช ์ค๋ช
Windows | closesocket() | ์์ผ ์ข ๋ฃ ๋ฐ ๋ฆฌ์์ค ํด์ |
Linux/Unix | close() | ํ์ผ ๋์คํฌ๋ฆฝํฐ ๋ฐฉ์ ์์ผ ์ข ๋ฃ |
โ ์ค๋ฌด ์์ฝ ํ๋ฆ (Windows ๊ธฐ์ค)
plaintext
๋ณต์ฌํธ์ง
[WSAStartup()] → [socket()] → [์ฌ์ฉ] → [closesocket()] → [WSACleanup()]
Linux๋ WSAStartup() / WSACleanup() ๊ณผ์ ์์ด ๋ฐ๋ก socket() ~ close() ์ฌ์ฉ
๐ ์ถ๊ฐ ์์ฝ ๋ฉ๋ชจ
- socket() ๋ฆฌํด๊ฐ์ ์คํจ ์ INVALID_SOCKET (Windows) / 1 (Linux)
- ๋ฆฌํด๊ฐ ํ์ธ ํ ์ฆ์ ์ค๋ฅ ์ฝ๋ ์ถ์ ํ๋ ์ต๊ด ์ค์
- ๋ชจ๋ ๋ฆฌ์์ค๋ ์ฌ์ฉ ํ ๋ฐ๋์ ํด์ (closesocket() ๋๋ close())
์ข์, ์๋๋ ์ฐ์ต๋ฌธ์ 01~05-A๊น์ง์ ๋ํ ์๊ตฌ์ฌํญ ํด์ → ์ฝ๋ ์์ → ๊ฒฐ๊ณผ ํด์ค ํ๋ฆ์ผ๋ก ์ ๋ฆฌํ ์์ฑ๋ ๋์ ํด์ค์ด๋ค. Windows ํ๊ฒฝ์์์ Winsock ํ๋ก๊ทธ๋๋ฐ์ ๊ธฐ์ด๋ถํฐ ์์ฉ๊น์ง ์ฒด๊ณ์ ์ผ๋ก ๋ค๋ฃฐ ์ ์๋๋ก ์ค๊ณํ์ผ๋ฉฐ, InitSocket ์์ ์์ ๊ณผ ์ฌ์ฉ์ ์ ์ ํจ์ ์ค๋ฅ ์ฒ๋ฆฌ ๋ก์ง๊น์ง ๋ชจ๋ ํฌํจํ๋ค.
โ ์ฐ์ต๋ฌธ์ 01: wsa ๋ณ์์ ์ฃผ์ ํ๋ ์ถ๋ ฅ
๐ง ์๊ตฌ ์ฌํญ
- WSADATA ๊ตฌ์กฐ์ฒด์ ๋ค์ 4๊ฐ ํ๋๋ฅผ ์ถ๋ ฅ
- wVersion, wHighVersion, szDescription, szSystemStatus
- Winsock 1.1 ๋ฒ์ ์์ฒญ(MAKEWORD(1,1)) ์ ๊ฐ ๋น๊ต
๐ ์ฝ๋ ์์
cpp
๋ณต์ฌํธ์ง
#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32")
int main() {
WSADATA wsa;
int result = WSAStartup(MAKEWORD(1, 1), &wsa);
if (result != 0) {
printf("WSAStartup ์คํจ: %d\\n", result);
return 1;
}
printf("wVersion: %x\\n", wsa.wVersion);
printf("wHighVersion: %x\\n", wsa.wHighVersion);
printf("szDescription: %s\\n", wsa.szDescription);
printf("szSystemStatus: %s\\n", wsa.szSystemStatus);
WSACleanup();
return 0;
}
๐ก ๊ฒฐ๊ณผ ์์ (๋ฒ์ 1.1 ์์ฒญ ์)
plaintext
๋ณต์ฌํธ์ง
wVersion: 101
wHighVersion: 202
szDescription: WinSock 2.0
szSystemStatus: Running
โ wVersion์ ์์ฒญ๋ ๋ฒ์ , wHighVersion์ ์ง์ ๊ฐ๋ฅํ ์ต๋ ๋ฒ์
โ ์ฐ์ต๋ฌธ์ 02-A / 02-B: UDP ์์ผ ์์ฑ
๐ ์ฝ๋ ์์ (IPv4 ๊ธฐ๋ฐ UDP)
cpp
๋ณต์ฌํธ์ง
SOCKET udp_sock = socket(AF_INET, SOCK_DGRAM, 0);
if (udp_sock == INVALID_SOCKET)
err_quit("UDP ์์ผ ์์ฑ ์คํจ");
โ SOCK_DGRAM, protocol = 0 → UDP
โ ์ฐ์ต๋ฌธ์ 03-A / 03-B: IPv6 ๊ธฐ๋ฐ TCP ์์ผ ์์ฑ
๐ ์ฝ๋ ์์
cpp
๋ณต์ฌํธ์ง
SOCKET tcp6_sock = socket(AF_INET6, SOCK_STREAM, 0);
if (tcp6_sock == INVALID_SOCKET)
err_quit("IPv6 TCP ์์ผ ์์ฑ ์คํจ");
โ AF_INET6์ผ๋ก ์ฃผ์ ์ฒด๊ณ๋ฅผ IPv6๋ก ์ค์
โ ์ฐ์ต๋ฌธ์ 04-A / 04-B: IPv6 ๊ธฐ๋ฐ UDP ์์ผ ์์ฑ
๐ ์ฝ๋ ์์
cpp
๋ณต์ฌํธ์ง
SOCKET udp6_sock = socket(AF_INET6, SOCK_DGRAM, 0);
if (udp6_sock == INVALID_SOCKET)
err_quit("IPv6 UDP ์์ผ ์์ฑ ์คํจ");
โ ์ฐ์ต๋ฌธ์ 05-A: ์ฌ์ฉ์ ์ ์ ํจ์ ์ค๋ฅ ์ฒ๋ฆฌ (WSASetLastError ์ฌ์ฉ)
๐ง ์๊ตฌ ์ฌํญ
- ์ ๋ ฅ๊ฐ์ด ์์๋ฉด SOCKET_ERROR ๋ฐํ, **WSASetLastError()**๋ก ์ค๋ฅ ์ฝ๋ ์ง์
- ์ฑ๊ณต์ด๋ฉด 0, ์ค๋ฅ์ฝ๋๋ 0
๐ ์ฝ๋ ์์
cpp
๋ณต์ฌํธ์ง
#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32")
void err_quit(const char* msg) {
fprintf(stderr, "[์ค๋ฅ] %s: %d\\n", msg, WSAGetLastError());
exit(1);
}
int f(int x) {
if (x >= 0) {
WSASetLastError(0);
return 0;
} else {
WSASetLastError(WSAEINVAL); // Invalid argument
return SOCKET_ERROR;
}
}
int main() {
WSAStartup(MAKEWORD(2, 2), &(WSADATA){0});
int retval = f(-100);
if (retval == SOCKET_ERROR)
err_quit("f()");
WSACleanup();
return 0;
}
๐ก ์ถ๋ ฅ ์์
plaintext
๋ณต์ฌํธ์ง
[์ค๋ฅ] f(): 10022
โ 10022๋ WSAEINVAL์ ํด๋นํ๋ ์ค๋ฅ ์ฝ๋ (Invalid argument)
๐ ์ ์ฒด ์์ฝ
๋ฌธ์ ์ฃผ์ ํฌ์ธํธ
01 | WSADATA ํ๋ ํด์ ๋ฐ ๋ฒ์ ๋ณํ ๊ด์ฐฐ |
02 | UDP ์์ผ ์์ฑ: SOCK_DGRAM, AF_INET |
03 | IPv6 TCP ์์ผ ์์ฑ: AF_INET6, SOCK_STREAM |
04 | IPv6 UDP ์์ผ ์์ฑ: AF_INET6, SOCK_DGRAM |
05 | ์ฌ์ฉ์ ์ ์ ์ค๋ฅ ์ฒ๋ฆฌ ํจ์: WSASetLastError() ํ์ฉ |
์ข์, ์ฌ๊ธฐ์๋ ์ค์ต 2-2์ ํต์ฌ์ธ ์์ผ ์์ฑ๊ณผ ๋ซ๊ธฐ (์๋์ฐ vs ๋ฆฌ๋ ์ค) ๋ฅผ ์ค์ต ํ๊ฒฝ์ ๋ง๊ฒ ๋ถ๋ฆฌํ์ฌ ๊ตฌ์ฑํ๊ณ , ์ค์ ์ฝ๋ ์ค๋ช ๊น์ง ์ ๋ฆฌํด์ค๊ฒ. ๋ชฉ์ ์ ์์ผ์ ๋ง๋ค๊ณ → ์ฑ๊ณต ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํ๊ณ → ๋ซ๋ ์ผ๋ จ์ ๊ณผ์ ์ ํตํด ์์ผ ํ๋ก๊ทธ๋๋ฐ์ ๊ฐ์ฅ ๊ธฐ๋ณธ ๋ฃจํด์ ์ฒด๋ํ๋ ๊ฒ์ด์ผ.
โ ์ค์ต 2-2: ์์ผ ์์ฑ๊ณผ ๋ซ๊ธฐ
๐ฅ๏ธ Windows ํ๊ฒฝ: InitSocket.cpp
cpp
๋ณต์ฌํธ์ง
#include "..\\..\\Common.h"
int main(int argc, char* argv[]) {
// 1. ์์ ์ด๊ธฐํ
WSADATA wsa;
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
return 1;
printf("[์๋ฆผ] ์์ ์ด๊ธฐํ ์ฑ๊ณต\\n");
// 2. ์์ผ ์์ฑ (IPv4, TCP)
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET)
err_quit("socket()");
printf("[์๋ฆผ] ์์ผ ์์ฑ ์ฑ๊ณต\\n");
// 3. ์์ผ ๋ซ๊ธฐ
closesocket(sock);
// 4. ์์ ์ข
๋ฃ
WSACleanup();
return 0;
}
๐ ํฌ์ธํธ ์์ฝ
๋จ๊ณ ํจ์ ์ค๋ช
1 | WSAStartup() | Winsock ์ด๊ธฐํ (ํ์) |
2 | socket() | ์์ผ ์์ฑ (IPv4 + TCP) |
3 | closesocket() | ์์ผ ์์ ๋ฐํ |
4 | WSACleanup() | Winsock ์ข ๋ฃ ๋ฐ ์ ๋ฆฌ |
err_quit() ํจ์๋ Common.h์ ์ ์๋ ์ฌ์ฉ์ ์ ์ ์ค๋ฅ ์ถ๋ ฅ ํจ์. WSAGetLastError()๋ฅผ ํจ๊ป ์ถ๋ ฅํจ.
๐ง Linux ํ๊ฒฝ: InitSocket.cpp
cpp
๋ณต์ฌํธ์ง
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> // close()
#include <sys/socket.h> // socket()
#include <netinet/in.h> // AF_INET
int main(int argc, char* argv[]) {
// 1. ์์ผ ์์ฑ (IPv4, TCP)
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket()");
exit(1);
}
printf("[์๋ฆผ] ์์ผ ์์ฑ ์ฑ๊ณต\\n");
// 2. ์์ผ ๋ซ๊ธฐ
close(sock);
return 0;
}
๐ Linux ํฌ์ธํธ ์ฐจ์ด
ํญ๋ชฉ ์๋์ฐ ๋ฆฌ๋ ์ค
์ด๊ธฐํ | WSAStartup() | ํ์ ์์ |
์ข ๋ฃ | WSACleanup() | ํ์ ์์ |
์์ผ ํ์ | SOCKET (typedef) | int |
๋ซ๊ธฐ ํจ์ | closesocket() | close() |
์ค๋ฅ ์ฝ๋ | WSAGetLastError() | errno + perror() |
๐ ์ฝ์ ๊ฒฐ๊ณผ ์์
plaintext
๋ณต์ฌํธ์ง
[์๋ฆผ] ์์ ์ด๊ธฐํ ์ฑ๊ณต
[์๋ฆผ] ์์ผ ์์ฑ ์ฑ๊ณต
→ ์ฑ๊ณต ํ ์ข
๋ฃ
๋๋ Linux์์:
bash
๋ณต์ฌํธ์ง
$ ./InitSocket
[์๋ฆผ] ์์ผ ์์ฑ ์ฑ๊ณต
โ ์์ฝ ํ๋ฆ
plaintext
๋ณต์ฌํธ์ง
[์์ผ ์์ฑ]
↓
[์๋ฌ ํ์ธ]
↓
[์ ์ ๋ฉ์์ง ์ถ๋ ฅ]
↓
[์์ ์ ๋ฆฌ (close)]
๐ ์ค์ต ์ฐ์ฅ ์์ด๋์ด
- AF_INET6 ๊ธฐ๋ฐ์ผ๋ก ์์ผ ์์ฑ ์๋ํด๋ณด๊ธฐ
- **SOCK_DGRAM**์ผ๋ก UDP ์์ผ ์ค์ต
- ์คํจ ์ ์ค๋ฅ ์ฝ๋ ์ถ๋ ฅ ๋ฐ ๋ฉ์์งํ ์ฐ์ต
์ด ์ ์์๋ ์์ผ ํ๋ก๊ทธ๋๋ฐ์์์ "์ฃผ์ ์ฒด๊ณ(Address Family)"์ "์์ผ ํ์ (Socket Type)"์ ๊ฐ๋ ๊ณผ ์ญํ ์ ๋ช ํํ ์ค๋ช ํ๊ณ ์๋ค. ์ค๋ฌด์ ์ผ๋ก๋ socket() ํจ์์ ์ฒซ ๋ฒ์งธ์ ๋ ๋ฒ์งธ ์ธ์๋ฅผ ์ ํํ ์ดํดํ๊ณ ์ค์ ํ๋ ๊ฒ์ด ๊ฐ์ฅ ๊ธฐ์ด์ด์ ํต์ฌ์ด๋ค. ์๋ ๋ด์ฉ์ ์์ฝ๊ณผ ๋์ ์ค์ฌ์ผ๋ก ์ฌ๊ตฌ์ฑํด ์ค๊ฒ.
โ ์์ผ ํ๋ก๊ทธ๋๋ฐ์์์ ์ฃผ์ ์ฒด๊ณ์ ์์ผ ํ์
๐ 1. ์ฃผ์ ์ฒด๊ณ (Address Family)
๊ฐ๋ :
- ํต์ ๋์์ ์ฃผ์ ํ์์ ์ ์
- ์ด๋ค ๋คํธ์ํฌ ํ๋กํ ์ฝ(IP, Bluetooth ๋ฑ)์ ์ฌ์ฉํ ์ง๋ฅผ ์ ํํจ
๋ํ ์ฃผ์ ์ฒด๊ณ ๊ฐ
์ฌ์ฉ ๋ชฉ์ ์์ซ๊ฐ ์ค๋ช
IPv4 ํต์ | AF_INET | IPv4 ์ฃผ์ ์ฌ์ฉ (์: 192.168.0.1) |
IPv6 ํต์ | AF_INET6 | IPv6 ์ฃผ์ ์ฌ์ฉ (์: 2001:abcd::1) |
Bluetooth ํต์ | AF_BTH | ๋ธ๋ฃจํฌ์ค ํต์ ์ฉ |
Unix Domain Socket | AF_UNIX | ๋ก์ปฌ ํ๋ก์ธ์ค ๊ฐ ํต์ (๋ฆฌ๋ ์ค ์ ์ฉ) |
โ socket() ํจ์์ ์ฒซ ๋ฒ์งธ ์ธ์๋ก ์ฌ์ฉ๋จ
๐ 2. ์์ผ ํ์ (Socket Type)
๊ฐ๋ :
- ๋ฐ์ดํฐ ์ ์ก ๋ฐฉ์ ๋ฐ ์ ๋ขฐ์ฑ ์ฌ๋ถ๋ฅผ ๊ฒฐ์
- TCP/UDP ๋๋ ๋ค๋ฅธ ํ๋กํ ์ฝ์ ์ฌ์ฉํ ๋์ ์ ์ก ํน์ฑ์ ์ ์
๋ํ ์์ผ ํ์ ๊ฐ
์์ผ ํ์ ํน์ฑ ์ค๋ช
SOCK_STREAM | ์ฐ๊ฒฐํ, ์ ๋ขฐ์ฑ ๋ณด์ฅ (ex. TCP) |
SOCK_DGRAM | ๋น์ฐ๊ฒฐํ, ์ ๋ขฐ์ฑ ์์ (ex. UDP) |
โ socket() ํจ์์ ๋ ๋ฒ์งธ ์ธ์๋ก ์ฌ์ฉ๋จ
๐งญ ์ข ํฉ ์ค์ ๊ฐ์ด๋: TCP vs UDP
์ฌ์ฉํ ํ๋กํ ์ฝ ์ฃผ์ ์ฒด๊ณ (af) ์์ผ ํ์ (type)
TCP (IPv4/6) | AF_INET ๋๋ AF_INET6 | SOCK_STREAM |
UDP (IPv4/6) | AF_INET ๋๋ AF_INET6 | SOCK_DGRAM |
ํ๋กํ ์ฝ ๋ฒํธ๋ ์ผ๋ฐ์ ์ผ๋ก 0์ ์ ๋ ฅํ๋ฉด type์ ๋ง์ถฐ ์๋์ผ๋ก ์ค์ ๋จ
๐ ์ค๋ฌด ๋ฉ๋ชจ: ํ์ ํธํ์ฑ๊ณผ SOCKET ์ ์
- Windows:
- **SOCKET**์ ์ ์๋ ์๋ฃํ (unsigned int ๋ฑ) → closesocket() ์ฌ์ฉ
- Linux:
- **socket()**์ int ํ์ ์ ๋ฐํ → close() ์ฌ์ฉ
- ํธํ์ฑ ํ๋ณด ๋ฐฉ๋ฒ:
- cpp ๋ณต์ฌํธ์ง // Linux์์ Windows ์ฝ๋์ ๋์ผํ๊ฒ ์ฌ์ฉ ๊ฐ๋ฅํ๋๋ก ๋งคํ typedef int SOCKET
๊ฒฐ๋ก ์์ฝ
plaintext
๋ณต์ฌํธ์ง
[1๋จ๊ณ] ์ฃผ์ ์ฒด๊ณ ์ ํ (IPv4 vs IPv6 ๋ฑ)
↓
[2๋จ๊ณ] ์์ผ ํ์
์ ํ (TCP vs UDP ๋ฑ)
↓
[3๋จ๊ณ] socket() ํธ์ถ → SOCKET ํธ๋ค ๋ฐํ
์ด ๊ตฌ์กฐ๊ฐ ๋ฐ๋ก ๋ชจ๋ ๋คํธ์ํฌ ํ๋ก๊ทธ๋จ์ ์์์ ์ด ๋๋ ์์ผ ์์ฑ ๊ธฐ๋ณธ ๊ณต์์ด์ผ.
์ด๋ฒ ์ ์ socket() ํจ์์ ์ธ ๋ฒ์งธ ์ธ์์ธ ํ๋กํ ์ฝ ์ง์ ๋ฐฉ๋ฒ, ๊ทธ๋ฆฌ๊ณ ์์ผ์ ์ข ๋ฃํ ๋ ์ฌ์ฉํ๋ closesocket() vs close() ํจ์์ ๋ํ ์ ๋ฆฌ๋ฅผ ๋ค๋ฃจ๊ณ ์์ด. ์ค๋ฌด์์๋ ๋น๋ฒํ๊ฒ ๋ฐ์ํ๋ ํผ์ฉ ์ผ์ด์ค(AF vs PF), ๋ฆฌ์์ค ๋์ ๋ฐฉ์ง ๊ด๋ จํด์๋ ์ค์ํ ๊ฐ๋ ์ด๋, ์ค์ต ๊ด์ ์ผ๋ก ์ฌ์ ๋ฆฌํด์ค๊ฒ.
โ ์์ผ ์์ฑ ์ ํ๋กํ ์ฝ ์ค์ + ์์ผ ๋ซ๊ธฐ
๐ 1. socket() ํจ์์ ์ธ ๋ฒ์งธ ์ธ์: ํ๋กํ ์ฝ (Protocol)
๐ง ์ญํ
- ๋์ผํ ์ฃผ์ ์ฒด๊ณ(AF_)์ ์์ผ ํ์ (SOCK_) ์กฐํฉ์์ ๋ช ํํ ํ๋กํ ์ฝ ์ ํ์ด ํ์ํ ๋ ์ฌ์ฉ
์์: socket() ํจ์ ์๊ทธ๋์ฒ
c
๋ณต์ฌํธ์ง
int socket(int domain, int type, int protocol);
[ํ 2-4] TCP์ UDP ์ค์
์ฌ์ฉํ ํ๋กํ ์ฝ ์ฃผ์ ์ฒด๊ณ (domain) ์์ผ ํ์ (type) ํ๋กํ ์ฝ (protocol)
TCP | AF_INET, AF_INET6 | SOCK_STREAM | IPPROTO_TCP (or 0) |
UDP | AF_INET, AF_INET6 | SOCK_DGRAM | IPPROTO_UDP (or 0) |
โ ๏ธ ์ค๋ฌด์์๋ protocol ์๋ฆฌ์ ๋ณดํต 0์ ๋ฃ์ผ๋ฉด, type์ ๋ฐ๋ผ TCP/UDP๊ฐ ์๋์ผ๋ก ๊ฒฐ์ ๋จ
๐ ํ๋กํ ์ฝ ๊ฐ ์์ ์์ฝ
์ด๋ฆ ๊ฐ (๋ณดํต) ์ค๋ช
IPPROTO_TCP | 6 | TCP ํ๋กํ ์ฝ |
IPPROTO_UDP | 17 | UDP ํ๋กํ ์ฝ |
0 | ์๋ ์ง์ | type ๊ฐ ๊ธฐ์ค ์๋ ์ค์ |
๐ 2. AF_INET vs PF_INET
์ค์ต ์ค ํท๊ฐ๋ฆด ์ ์๋ ๊ฐ๋ , ํ์คํ ์ ๋ฆฌํด๋ณด์.
๊ตฌ๋ถ ์๋ฏธ ์ค์ ๊ฐ ๋์ผ ์ฌ์ฉ ์์น (๊ณผ๊ฑฐ ๊ธฐ์ค)
AF_INET | Address Family (์ฃผ์ ์ฒด๊ณ) | โ ๊ฐ์ | ์์ผ ์ฃผ์ ๊ตฌ์กฐ์ฒด ์ฌ์ฉ (์: struct sockaddr_in) |
PF_INET | Protocol Family (ํ๋กํ ์ฝ ๊ณ์ด) | โ ๊ฐ์ | socket() ํจ์์์ ์ฌ์ฉ |
โ ์ง๊ธ์ ๋๋ถ๋ถ์ ๋ฌธ์์ ์ฝ๋์์ AF_ ๊ณ์ด๋ก ํต์ผํ์ฌ ์ฌ์ฉ
๐ 3. ์์ผ ๋ซ๊ธฐ (closesocket() vs close())
โ Windows
c
๋ณต์ฌํธ์ง
#include <winsock2.h>
int closesocket(SOCKET s); // ๋ฆฌํด๊ฐ: ์ฑ๊ณต 0, ์คํจ SOCKET_ERROR
โ Linux
c
๋ณต์ฌํธ์ง
#include <unistd.h>
int close(int fd); // ๋ฆฌํด๊ฐ: ์ฑ๊ณต 0, ์คํจ -1
๐ ์ฃผ์ํ ์
ํญ๋ชฉ Windows Linux
์์ผ ํ์ | SOCKET | int (ํ์ผ ๋์คํฌ๋ฆฝํฐ) |
๋ซ๊ธฐ ํจ์ | closesocket() | close() |
์ค๋ฅ ํ์ธ | WSAGetLastError() | errno / perror() |
โ ๏ธ close()๋ก Winsock ์์ผ์ ์ข ๋ฃํ๋ฉด ๋ฆฌ์์ค ํด์ ๊ฐ ๋ถ์์ ํด์ง ์ ์์ → Windows์์๋ closesocket() ํ์
๐งญ ์ข ํฉ ํ๋ฆ: ์์ผ ์์ฑ ~ ์ข ๋ฃ
c
๋ณต์ฌํธ์ง
// 1. ์์ผ ์์ฑ (TCP ์์)
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // or 0
// 2. ํต์ ์์
// 3. ์์ผ ์ข
๋ฃ
closesocket(sock); // Windows
close(sock); // Linux
๐ ์ ๋ฆฌ ๋ฉ๋ชจ
๊ฐ๋ ํค์๋ ์ค๋ช
์ฃผ์ ์ฒด๊ณ | AF_INET, AF_INET6 | IPv4/IPv6์ฉ ์ฃผ์ ์ง์ |
์์ผ ํ์ | SOCK_STREAM, SOCK_DGRAM | TCP/UDP ์ ์ก ์ ํ |
ํ๋กํ ์ฝ | IPPROTO_TCP, IPPROTO_UDP, 0 | ๋ช ์ ๋๋ ์๋ ์ง์ |
์์ผ ์ข ๋ฃ | closesocket() vs close() | ํ๋ซํผ๋ณ ์ข ๋ฃ ๋ฐฉ์ |
AF vs PF | ์ค์ง์ ์ฐจ์ด ์์ | AF_INET ์ฌ์ฉ ๊ถ์ฅ |
์ด๋ฒ ์ ์ ์์ผ ํ๋ก๊ทธ๋๋ฐ์ ๊ฐ์ฅ ๊ธฐ๋ณธ์ด ๋๋ socket() ํจ์ ํธ์ถ ๋ฐฉ์, ์ฆ ์์ผ์ ์์ฑ๊ณผ ๊ฐ๋ ์ ์ง์คํ๊ณ ์์ด. Windows์ Linux ๊ฐ์ ์ฐจ์ด์ , ๊ทธ๋ฆฌ๊ณ socket() ํจ์ ํธ์ถ ์ ์ ๋ฌํด์ผ ํ๋ ์ธ ๊ฐ์ง ํต์ฌ ์ธ์ — ์ฃผ์ ์ฒด๊ณ, ์์ผ ํ์ , ํ๋กํ ์ฝ — ์ ๋ํด ์์ฃผ ์ค์ํ๊ณ ๋ ์ค์ฉ์ ์ธ ๋ด์ฉ์ ๋ค๋ฃจ๊ณ ์์ด.
์๋์ ๊ตฌ์กฐํํด์ ํต์ฌ ์์ฝ๊ณผ ์ค์ตํ ์ฝ๋๊น์ง ์ ๋ฆฌํด์ค๊ฒ.
โ Chapter 03: ์์ผ ์์ฑ๊ณผ ๋ซ๊ธฐ – ํต์ฌ ์์ฝ
๐ 1. ์์ผ ์์ฑ์ด๋?
- socket() ํจ์๋ ๋คํธ์ํฌ ํต์ ์ ์ํ ํธ๋ค(=์์ผ ๋์คํฌ๋ฆฝํฐ) ์ ์์ฑ
- ์ด ํธ๋ค์ ๋คํธ์ํฌ ์์์ ๋ํ ์ ๊ทผ ๊ถํ์ ์๋ฏธ
- ์์ฑ๋ ์์ผ ๋์คํฌ๋ฆฝํฐ๋ ์ดํ bind(), connect(), send(), recv() ๋ฑ์ ํจ์์ ์ ๋ฌ
๐งฉ socket() ํจ์ ํ๋กํ ํ์ ๋น๊ต
OS ํจ์ ์ ์ ์ค๋ช
Windows | SOCKET socket(int af, int type, int protocol); | **SOCKET**์ ๋ณ๋ ์ ์๋ ํ์ |
Linux | int socket(int domain, int type, int protocol); | **int**ํ ํ์ผ ๋์คํฌ๋ฆฝํฐ |
โ ๋ฐํ๊ฐ์ ๋ ๋ค ์์ผ ํธ๋ค๊ฐ, ์คํจ ์ INVALID_SOCKET (Windows) ๋๋ -1 (Linux)
๐งญ socket() ํจ์์ ์ธ ๊ฐ์ง ์ธ์
์ธ์ ์ด๋ฆ ์ค๋ช ๋ฐ ์์ ๊ฐ
1 | ์ฃผ์ ์ฒด๊ณ | AF_INET, AF_INET6 (IPv4/6), AF_BLUETOOTH, AF_UNIX |
2 | ์์ผ ํ์ | SOCK_STREAM (TCP), SOCK_DGRAM (UDP) |
3 | ํ๋กํ ์ฝ |
๐ป ์์ ์ฝ๋ – Windows (TCP ์์ผ ์์ฑ)
cpp
๋ณต์ฌํธ์ง
#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32")
int main() {
WSADATA wsa;
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
return 1;
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); // TCP
if (sock == INVALID_SOCKET) {
printf("์์ผ ์์ฑ ์คํจ\\n");
WSACleanup();
return 1;
}
printf("์์ผ ์์ฑ ์ฑ๊ณต: %d\\n", (int)sock);
closesocket(sock);
WSACleanup();
return 0;
}
๐ง ์์ ์ฝ๋ – Linux (UDP ์์ผ ์์ฑ)
c
๋ณต์ฌํธ์ง
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main() {
int sock = socket(AF_INET, SOCK_DGRAM, 0); // UDP
if (sock < 0) {
perror("์์ผ ์์ฑ ์คํจ");
exit(1);
}
printf("์์ผ ์์ฑ ์ฑ๊ณต: %d\\n", sock);
close(sock);
return 0;
}
๐ ์ ๋ฆฌ: ์์ผ ์์ฑ ํต์ฌ ํฌ์ธํธ
ํญ๋ชฉ ๋ด์ฉ
ํ๋ซํผ ์ฐจ์ด | Windows: WSAStartup() ํ์ / ๋ฆฌ๋ ์ค๋ ์์ |
๋ฆฌํด๊ฐ | ์คํจ ์ Windows: INVALID_SOCKET, Linux: -1 |
ํด๋ก์ง | Windows: closesocket() / Linux: close() |
์ผ๋ฐ ์ค์ | TCP: AF_INET, SOCK_STREAM, 0 / UDP: AF_INET, SOCK_DGRAM, 0 |
'Development๐ฉ๐ปโ๐ฆณ > Communication' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
์์ผ ํต์ ์ ๋๋ก ์ดํดํ๊ธฐ: TCP/IP 4๊ณ์ธต์ ์ค์ฌ์ผ๋ก (0) | 2025.04.10 |
---|