π‘ λ³Έ λ¬Έμλ 'Socket μμΌ νλ‘κ·Έλλ°'μ λν΄ μ 리ν΄λμ κΈμ λλ€.
C/C++μμ "sys/socket.h"μ μ¬μ©νμ¬ μμΌ νλ‘κ·Έλλ°νλ λ°©λ²μ λν΄ μ 리νμμΌλ μ°Έκ³ νμκΈ° λ°λλλ€.
1. μμΌ ν΅μ μ΄λ?
1.1 μμΌ(Socket) μ΄λ?
μμΌ(Socket)μ νλ‘μΈμ€κ° λ€νΈμν¬ μΈκ³λ‘ λ°μ΄ν°λ₯Ό λ΄λ³΄λ΄κ±°λ νΉμ κ·Έ μΈκ³λ‘λΆν° λ°μ΄ν°λ₯Ό λ°κΈ° μν μ€μ μ μΈ μ°½κ΅¬ μν μ ν©λλ€. κ·Έλ¬λ―λ‘ νλ‘μΈμ€κ° λ°μ΄ν°λ₯Ό 보λ΄κ±°λ λ°κΈ° μν΄μλ λ°λμ μμΌμ μ΄μ΄μ μμΌμ λ°μ΄ν°λ₯Ό μ¨λ³΄λ΄κ±°λ μμΌμΌλ‘λΆν° λ°μ΄ν°λ₯Ό μ½μ΄λ€μ¬μΌ ν©λλ€.
- νλ‘ν μ½(protocol): μλ μΈκ΅μμ μΈμ΄λ‘μ¨ μλ‘λ κ΅κ°κ°μ μ½μμ μλ―Ένλ©°, ν΅μ μμλ μ΄λ€ μμ€ν μ΄ λ€λ₯Έ μμ€ν κ³Ό ν΅μ μ μννκ² μμ©νλλ‘ ν΄μ£Όλ ν΅μ κ·μ½μ λλ€.
- IP: μ μΈκ³ μ»΄ν¨ν°μ λΆμ¬λ κ³ μ μ μλ³ μ£Όμ
- ν¬νΈ(port): λ€νΈμν¬ μμμ ν΅μ νκΈ° μν΄μ νΈμ€νΈ λ΄λΆμ μΌλ‘ νλ‘μΈμ€κ° ν λΉλ°μμΌ νλ κ³ μ ν μ«μμ λλ€. ν νΈμ€νΈ λ΄μμ λ€νΈμν¬ ν΅μ μ νκ³ μλ νλ‘μΈμ€λ₯Ό μλ³νκΈ° μν΄ μ¬μ©λλ κ°μ΄λ―λ‘, κ°μ νΈμ€νΈ λ΄μμ μλ‘ λ€λ₯Έ νλ‘μΈμ€κ° κ°μ ν¬νΈ λλ²λ₯Ό κ°μ§ μ μλ€. μ¦, κ°μ μ»΄ν¨ν° λ΄μμ νλ‘κ·Έλ¨μ μλ³νλ λ²νΈμ λλ€.
λ€μλ§ν΄ μμΌμ΄μ λ¨μ΄μ Έ μλ λ νΈμ€νΈλ₯Ό μ°κ²°ν΄μ£Όλ λꡬλ‘μ¨ μΈν°νμ΄μ€μ μν μ νλλ° λ°μ΄ν°λ₯Ό μ£Όκ³ λ°μ μ μλ κ΅¬μ‘°μ²΄λ‘ μμΌμ ν΅ν΄ λ°μ΄ν° ν΅λ‘κ° λ§λ€μ΄ μ§λλ€. μ΄λ¬ν μμΌμ μν μ λ°λΌ μλ² μμΌ, ν΄λΌμ΄μΈνΈ μμΌμΌλ‘ ꡬλΆλ©λλ€.
1.2 μμΌν΅μ μ νλ¦
1.2.1 μλ² (Server)
ν΄λΌμ΄μΈνΈ μμΌμ μ°κ²° μμ²μ λκΈ°νκ³ , μ°κ²° μμ²μ΄ μ€λ©΄ ν΄λΌμ΄μΈνΈ μμΌμ μμ±νμ¬ ν΅μ μ΄ κ°λ₯νκ² ν©λλ€.
- socket() ν¨μλ₯Ό μ΄μ©νμ¬ μμΌμ μμ±
- bind() ν¨μλ‘ ipμ port λ²νΈλ₯Ό μ€μ
- listen() ν¨μλ‘ ν΄λΌμ΄μΈνΈμ μ κ·Ό μμ²μ μμ λκΈ°μ΄μ λ§λ€μ΄ λͺ κ°μ ν΄λΌμ΄μΈνΈλ₯Ό λκΈ° μν¬μ§ κ²°μ
- accept() ν¨μλ₯Ό μ¬μ©νμ¬ ν΄λΌμ΄μΈνΈμμ μ°κ²°μ κΈ°λ€λ¦Ό
1.2.2 ν΄λΌμ΄μΈνΈ (Client)
- socket() ν¨μλ‘ κ°μ₯λ¨Όμ μμΌμ μ°λ€.
- connect() ν¨μλ₯Ό μ΄μ©νμ¬ ν΅μ ν μλ²μ μ€μ λ ipμ port λ²νΈμ ν΅μ μ μλ
- ν΅μ μ μλ μ, μλ²κ° accept() ν¨μλ₯Ό μ΄μ©νμ¬ ν΄λΌμ΄μΈνΈμ socket descriptorλ₯Ό λ°ν
- μ΄λ₯Ό ν΅ν΄ ν΄λΌμ΄μΈνΈμ μλ²κ° μλ‘ read(), write() λ₯Ό νλ©° ν΅μ (μ΄ κ³Όμ μ΄ λ°λ³΅)
1.3 μμΌμ’ λ₯
1.3.1 TCP λ°©μ: μ€νΈλ¦Ό(STREAM)
- μλ°©ν₯μΌλ‘ λ°μ΄νΈ μ€νΈλ¦Όμ μ μ‘, μ°κ²° μ§ν₯μ±
- μ€λ₯ μμ , μ μ‘μ²λ¦¬, νλ¦μ μ΄ λ³΄μ₯
- μ‘μ λ μμμ λ°λΌ μ€λ³΅λμ§ μκ² λ°μ΄ν°λ₯Ό μμ → μ€λ²ν€λκ° λ°μ
- μλμ λ°μ΄ν°λ³΄λ€ λλμ λ°μ΄ν° μ μ‘μ μ ν© → TCPλ₯Ό μ¬μ©
1.3.2 UDP λ°©μ: λ°μ΄ν°κ·Έλ¨(DGRAM)
- λΉμ°κ²°νμμΌ
- λ°μ΄ν°μ ν¬κΈ°μ μ νμ΄ μμ
- νμ€νκ² μ λ¬μ΄ 보μ₯λμ§ μμ, λ°μ΄ν°κ° μμ€λΌλ μ€λ₯κ° λ°μνμ§ μμ
- μ€μκ° λ©ν°λ―Έλμ΄ μ 보λ₯Ό μ²λ¦¬νκΈ° μν΄ μ£Όλ‘ μ¬μ© ex) μ ν
1.4 HTTP ν΅μ κ³Ό SOCKET ν΅μ μ λΉκ΅
1.4.1 HTTP ν΅μ
- Clientμ μμ²(Request)μ΄ μμ λλ§ μλ²κ° μλ΅(Response)νμ¬ ν΄λΉ μ 보λ₯Ό μ μ‘νκ³ κ³§λ°λ‘ μ°κ²°μ μ’ λ£νλ λ°©μ
1.4.2 HTTP ν΅μ μ νΉμ§
- Clientκ° μμ²μ 보λ΄λ κ²½μ°μλ§ Serverκ° μλ΅νλ λ¨λ°©ν₯ ν΅μ
- Serverλ‘λΆν° μλ΅μ λ°μ νμλ μ°κ²°μ΄ λ°λ‘ μ’ λ£
- μ€μκ° μ°κ²°μ΄ μλκ³ , νμν κ²½μ°μλ§ Serverλ‘ μμ²μ 보λ΄λ μν©μ μ μ©
- μμ²μ λ³΄λ΄ Serverμ μλ΅μ κΈ°λ€λ¦¬λ μ΄ν리μΌμ΄μ μ κ°λ°μ μ£Όλ‘ μ¬μ©
1.4.3 SOCKET ν΅μ
- Serverμ Clientκ° νΉμ Portλ₯Ό ν΅ν΄ μ€μκ°μΌλ‘ μλ°©ν₯ ν΅μ μ νλ λ°©μ
1.4.4 SOCKET ν΅μ μ νΉμ§
- Serverμ Clientκ° κ³μ μ°κ²°μ μ μ§νλ μλ°©ν₯ ν΅μ
- Serverμ Clientκ° μ€μκ°μΌλ‘ λ°μ΄ν°λ₯Ό μ£Όκ³ λ°λ μν©μ΄ νμν κ²½μ°μ μ¬μ©
- μ€μκ° λμμ Streamingμ΄λ μ¨λΌμΈ κ²μ λ±κ³Ό κ°μ κ²½μ°μ μμ£Ό μ¬μ©
2. μμΌ ν΅μ μ μ°μ΄λ ꡬ쑰체
리λ μ€/μ λμ€ μμ€ν μμλ μμΌ(socket)μ ν΅μ λμμ μ§μ νκΈ° μν΄ 'μ£Όμ(address)'λ₯Ό μ¬μ©ν©λλ€. μ΄ 'μ£Όμ' λΌλ κ²μ μ μ₯νκ±°λ νννλλ° μ¬μ©νλ κ΅¬μ‘°μ²΄κ° 'sockaddr' μ λλ€.
2.0 νμν ν€λ νμΌ
μμΌ νλ‘κ·Έλλ°μ μν΄ νμν ν€λνμΌμ λ€μκ³Ό κ°μ΅λλ€. ν΄λΉ ν€λ νμΌμ μ΄ν μ€λͺ ν ꡬ쑰체μ ν¨μλ€μ΄ ꡬνλμ΄ μμ΅λλ€.
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> // μλ₯Ό λͺ¨λ ν¬ν¨
2.1 sockaddr ꡬ쑰체
μμΌμ ν΅ν΄ μ¬λ¬ ννμ λ€νΈμν¬λ₯Ό κ±°μ λΉμ·ν λ°©μμΌλ‘ λ°μ΄ν°λ₯Ό κ΅νν μ μμ΅λλ€. sockaddrλ μΌμ’ μ μΆμ ν΄λμ€μ²λΌ μμΌμΌλ‘ ν΅μ νκΈ° μν μ¬λ¬ λ€νΈμν¬μ μμ ꡬ쑰체μ λλ€. sockaddr μλ μΈν°λ·λ§μ μ¬μ©ν΄ ν΅μ νλ κ΅¬μ‘°μ²΄μΈ sockaddr_inκ³Ό μ λμ€ μ΄μ체μμ νλ‘μΈμ€κ° ν΅μ μ μν΄ μ¬μ©λλ sockaddr_unμ κ΅¬μ‘°μ²΄κ° μ μΈλμ΄ μμ΅λλ€.
/* sockaddr ꡬ쑰체 */
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
};
- sa_family: μμΌμ΄ μ¬μ©λλ λ€νΈμν¬μ μ’
λ₯μ
λλ€. λ€μ κ° μ€ νλκ° μ¬ μ μμ΅λλ€.
- AF_INET: IPv4λ₯Ό μ¬μ©νλ μΈν°λ·λ§μ μ μν©λλ€.
- AF_INET6: IPv6λ₯Ό μ¬μ©νλ μΈν°λ·λ§μ μ μν©λλ€.
- AF_LOCAL: μ λμ€ μ΄μ체μ μμ νλ‘μΈμ€κ° ν΅μ μ μνν©λλ€.
- sa_data: sa_familyκ°μ λ°λ₯Έ μ΅λ 14λ°μ΄νΈμ λΆκ° μ 보μ λλ€. μ΄ νλμ λ΄μ©μ sockaddr_inκ³Ό sockaddr_unμμ ꡬ체νλ©λλ€.
2.2 sockaddr_in ꡬ쑰체
inμ internetμ μκΈμμ λλ€. μμΌμ ν΅ν΄ μΈν°λ· λ§μ μ μνκΈ° μν ꡬ쑰체μ λλ€. AF_INET λͺ¨λμμ μ¬μ©ν μ μμ΅λλ€.
/* sockaddr_in ꡬ쑰체 */
struct sockaddr_in {
sa_family_t sin_family; // = νμ AF_INET
uint16_t sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
struct in_addr {
uint32_t s_addr;
};
- sin_family: sockaddrμ sa_familyμ κ°μ΅λλ€.
- sin_port: ν΅μ μ μν΄ μ¬μ©ν ν¬νΈ λ²νΈμ λλ€.
- sin_addr: μ μν λμ(μλλ°©)μ IP μ£Όμμ λλ€. μλ£νμΈ in_addr ꡬ쑰체λ Internet Addressμ μ€μ ννμΌλ‘ 4λ°μ΄νΈ IP μ£Όμλ₯Ό λνλ λλ€.
- sin_zero: sockaddrμμ sa_dataλ₯Ό ν΅ν΄ ν보ν 14λ°μ΄νΈ μΈ λλ¨Έμ§ κ³΅κ°μ λλ€. νμ 0μ΄λ©° μ¬μ©λμ§ μμ΅λλ€.
2.3 sockaddr_in6 ꡬ쑰체
AF_INET6 (IPv6)λ₯Ό μ¬μ©νλ λ€νΈμν¬μ μ μνκΈ° μν ꡬ쑰체μ λλ€.
/* sockaddr_in6 ꡬ쑰체 */
struct sockaddr_in6 {
sa_family_t sin6_family; // = νμ AF_INET6
in_port_t sin6_port;
uint32_t sin6_flowinfo;
struct in6_addr sin6_addr;
uint32_t sin6_scope_id;
};
struct in6_addr {
unsigned char s6_addr[16];
};
- sin6_family: sockaddrμ sa_familyμ κ°μ΅λλ€.
- sin6_port: ν΅μ μ μν΄ μ¬μ©ν ν¬νΈ λ²νΈμ λλ€.
- sin6_flowinfo: λΌμ°ν°κ° ν¨ν·μ΄ μ λ¬λλ κ²½λ‘λ₯Ό κ²°μ νλλ° νμν κ°μ λλ€.
- sin6_addr: μ μν λμ(μλλ°©)μ IP μ£Όμμ λλ€.
- sin6_scope_id: λ²μ μ λ°λΌ μ΄ λ©€λ²λ μμ μλ μμ΅λλ€. IP μ£Όμμ λ°λ₯Έ κ³μΈ΅μ΄ μ μ νμ§λ₯Ό κ²μ¦ν©λλ€. κ³μΈ΅μ μλ κ° μ€ νλμ
λλ€.
- 0x0: reserved, 0x1: interface-local, 0x2: link-local, 0x4: admin-local, 0x5: site-local, 0x8: organization-local, 0xe: global, 0xf: reserved
2.4 sockaddr_un ꡬ쑰체
μλ‘ λ€λ₯Έ νλ‘μΈμ€(μ€νμ€μΈ νλ‘κ·Έλ¨) μ¬μ΄μ λ°μ΄ν°λ₯Ό μ£Όκ³ λ°μμΌ ν λ μ¬μ©λλ ꡬ쑰체μ λλ€.
/* sockaddr_un ꡬ쑰체 */
struct sockaddr_un {
sa_family_t sun_family;
char sun_path[UNIX_PATH_MAX];
};
- sun_family: sockaddr ꡬ쑰체μ sa_familyμ κ°μ΅λλ€.
- sun_path: μμΌμΌλ‘ μ μν νμΌμ κ²½λ‘μ λλ€. UNIX_PATH_MAXλ μμ 108μ λλ€.
λ€μν ꡬ쑰체λ₯Ό μμ보μμΌλ, μ΄ μ€ κ°μ₯ 보νΈμ μΌλ‘ μ¬μ©λλ IPv4 ν΅μ μΈ sockaddr_in ꡬ쑰체λ₯Ό μ¬μ©ν΄ μΈν°λ·λ§μ μ°κ²°ν΄λ³΄κ² μ΅λλ€.
3. μμΌ ν΅μ νλ‘κ·Έλλ° (ν΄λΌμ΄μΈνΈ): TCP νλ‘ν μ½
- ν΄λΌμ΄μΈνΈ: μ μ λμμ sockaddr_in ꡬ쑰체 μΈν - socket() ν¨μ - connect() ν¨μμ 3λ¨κ³λ‘ μ μμ΄ μ§νλλ©°,
- μλ²: μμ μ sockaddr_in ꡬ쑰체 μΈν - socket() ν¨μ - bind() ν¨μ - listen() ν¨μ - accept() ν¨μμ 5λ¨κ³λ‘ μ μμ΄ μ§νλ©λλ€.
3.1 sockaddr_in ꡬ쑰체 μ€μ νκΈ°
μ μν λ€νΈμν¬, μ μ λμκ³Ό ν¬νΈ λ²νΈλ₯Ό μ€μ ν©λλ€.
/* sock_ex01.c */
struct sockaddr_in sock;
/* μ£Όμ 체κ³λ‘μ IPv4λ₯Ό μ¬μ©νλ μΈν°λ·λ§μ μ μ */
sock.sin_family = AF_INET;
/* μ μν λμμ 127.0.0.1 */
sock.sin_addr.s_addr = inet_addr("127.0.0.1");
/* ν¬νΈ λ²νΈλ 1435 */
sock.sin_port = htons(1435);
htons, htonl, htonll, htonf, htondμ ntohs, ntohl, ntohll, ntohf, ntohdλ λ°μ΄νΈ λ³ν ν¨μμ λλ€. htonκ³Ό ntohλ κ°κ° Host to Network, Network to Hostμ μ½μλ‘ Hostλ μ μ λ¨λ§κΈ°, Networkλ λ€νΈμν¬λ₯Ό ν΅ν΄ μ λ¬λλ κ²½λ‘λ₯Ό λ»ν©λλ€. Intel CPUλ₯Ό μ¬μ©νλ κ°μΈμ© μ»΄ν¨ν°λ Little Endianμ μ¬μ©νκ³ , μΌλΆ CPUλ Big Endian λ°©μμ μ¬μ©νμ§λ§, λ€νΈμν¬λ νμ Big EndianμΌλ‘ λ°μ΄ν°κ° μ λ¬λκΈ° λλ¬Έμ μ΄λ₯Ό λ³νν νμκ° μμ΅λλ€. htonκ³Ό ntoh λ€μ λΆλ s, l, ll, f, dλ μ μ‘λλ λ°μ΄ν°μ μλ£νμ λ»ν©λλ€.
- htons / ntohs : unsigned short νμ Endianμ λ³νν©λλ€.
- htonl / ntohl : unsigned long νμ Endianμ λ³νν©λλ€.
- htonll / ntohll : unslgned long νμ Endianμ λ³νν©λλ€.
- htonf / ntohf : float νμ Endianμ λ³νν©λλ€.
- htond / ntohd : double νμ Endianμ λ³νν©λλ€.
3.2 socket μμ±νκΈ°
IPv4λ₯Ό μ¬μ©νλ μΈν°λ·λ§μ μ μνκΈ° μν μμΌμ λ§λ€μ΄ λ³΄κ² μ΅λλ€.
/* μ¬μ© μ */
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
/* μμΌ λ§λ€κΈ°μ μ€ν¨ μ INVALID_SOCKETμ΄ λ°ν */
if(sock == INVALID_SOCKET) printf("Invalid Socket");
μ΄ μ€ socket() ν¨μλ λ°μ΄ν° κ΅νμ μν μμΌμ μμ±ν©λλ€. κΈ°λ³Έ 골격μ λ€μκ³Ό κ°μ΅λλ€.
SOCKET socket(int af, int type, int protocol);
af: μ μνλ λ°©μμ μ§μ ν©λλ€.
- AF_UNSPEC: κΈ°ν λ€νΈμν¬μ μ μν©λλ€.
- AF_INET: IPv4 μ£Όμ체κ³λ₯Ό μ¬μ©νλ μΈν°λ· λ§μ μ μν©λλ€.
- AF_IPX: IPX/SPX μ£Όμ체κ³λ₯Ό μ¬μ©νλ λ€νΈμν¬μ μ μν©λλ€. Windows μ΄μ체μ μ κ²½μ° Windows Vista μ΄νλ‘ μ§μνμ§ μλ λͺ¨λμ λλ€.
- AF_APPLETALK: AppleTalk λ€νΈμν¬μ μ μν©λλ€. Windows μ΄μ체μ μ κ²½μ° Windows Vista μ΄νλ‘ μ§μνμ§ μλ λͺ¨λμ λλ€.
- AF_NETBIOS: NetBIOS λ€νΈμν¬μ μ μν©λλ€. Windows μ΄μ체μ μ κ²½μ° 32λΉνΈ λ²μ μμλ§ μ΄ λͺ¨λκ° μ§μλ©λλ€.
- AF_INET6: IPv6 μ£Όμ체κ³λ₯Ό μ¬μ©νλ μΈν°λ·λ§μ μ μν©λλ€.
- AF_IRDA: μ μΈμ ν΅μ (IrDA)μΌλ‘ μλνΈμκ² μ μν©λλ€.
- AF_BTH: λΈλ£¨ν¬μ€λ‘ μλνΈμκ² μ μν©λλ€.
type: λ°μ΄ν°λ₯Ό κ΅ννλ λ°©μμ μ§μ ν©λλ€. μΌλ°μ μΌλ‘ TCP νλ‘ν μ½λ‘ ν΅μ ν λ SOCK_STREAM, UDP νλ‘ν μ½λ‘ ν΅μ ν λ SOCK_DGRAMμ μ¬μ©νκ³ , κ°κ³΅νμ§ μμ λ°©μμΌλ‘ μ§μ ν¨ν·μ μμ νκ±°λ ν¨ν·μ λ§λ€μ΄ ν΅μ ν λ SOCK_RAWλ₯Ό μ¬μ©ν©λλ€.
- SOCK_STREAM: μ /μΆλ ₯ μλμ μ€νΈλ¦Ό λ°©μμΌλ‘ λ°μ΄ν°λ₯Ό κ΅νν©λλ€. AF_INET, AF_INET6μμ μΌλ°μ μΌλ‘ μ¬μ©νλ λ°©μμ λλ€.
- SOCK_DGRAM: λ°μ΄ν°κ·Έλ¨μ ννλ‘ λ°μ΄ν°λ₯Ό κ΅νν©λλ€. AF_INET, AF_INET6μμλ UDP νλ‘ν μ½μ μ¬μ©ν λ μ΄ λ°©μμ΄ μ§μ λλ©°, NetBIOSλ μ΄ λ°©μμΌλ‘ μ§μ ν΄μΌ ν©λλ€.
- SOCK_RAW: μ μμ€μΌλ‘ λ°μ΄ν°λ₯Ό κ΅ννκ³ μ ν λ μ§μ λ©λλ€. IPv4 ν€λλ₯Ό μμ νκ³ μΆλ€λ©΄ IP_HDRINCL, IPv6 ν€λλ₯Ό μμ νκ³ μΆλ€λ©΄ IPV6_HDRINCL μ΅μ μ΄ ν¨κ» μ§μ λμ΄μΌ ν©λλ€.
- SOCK_RDM: λ©ν°μΊμ€νΈ(ν μλ²μμ λΌμ°ν°μ μ°κ²°λ λͺ¨λ μ»΄ν¨ν°λ‘ μΌκ΄μ μΌλ‘ λ°μ΄ν°λ₯Ό μ μ‘)λ₯Ό μ¬μ©νκ³ μΆμ λ μ§μ νλ λ°©μμ λλ€.
- SOCK_SEQPACKET: λͺ¨λ¦
protocol: μ¬μ©ν νλ‘ν μ½μ μ§μ ν©λλ€. IPPROTO_ICMP, IPPROTO_IGMP, BTHPROTO_RFCOMM, IPPROTO_TCP, IPPROTO_UDP, IPPROTO_ICMPV6, IPPROTO_RM λ±μ μ΄λ €μ΄ λ°©μλ€μ΄ μ΄κ±°λλλ° AF_INETμμλ κ·Έλ₯ μμ 0λ§ λ£μ΄λ λ©λλ€.
3.3 μμ±ν socketμΌλ‘ μλνΈμκ² μ μ
socket() ν¨μλ‘ μΈν°λ·λ§μ μ μνκΈ° μν μμΌμ μμ±νκ³ sockaddr_in κ΅¬μ‘°μ²΄λ‘ μ μν λμμ μ§μ νμμ΅λλ€. μλλ°©μκ² μ μνκΈ° μν ν¨μλ connectμ λλ€.
int connect(SOCKET s, const struct sockaddr * name, int namelen);
- s: μ μμ νμν μμΌμ λλ€.
- name: μμΌμΌλ‘ μ μν λμμ λλ€.
- namelen: nameμ ν¬κΈ°μ λλ€. sizeof μ°μ°μλ‘ sockaddr_in ꡬ쑰체μ ν¬κΈ°λ₯Ό μ λ ₯νλ©΄ λ©λλ€.
μ°κ²°μ μ±κ³΅νλ©΄ 0μ λ°ννμ§λ§, μ€ν¨ μ SOCKET_ERROR μμλ₯Ό λ°νν©λλ€.
3.4 κ°λ¨ν μμ μ½λ
/* μ¬μ© μ */
struct sockaddr_in sockaddr_internet;
SOCKET sock;
int connection;
/* -------- 1 λ¨κ³ -------- */
/* μ£Όμ 체κ³λ‘μ IPv4λ₯Ό μ¬μ©νλ μΈν°λ·λ§μ μ μ */
sockaddr_internet.sin_family = AF_INET;
/* μ μν λμμ 127.0.0.1 */
sockaddr_internet.sin_addr.s_addr = inet_addr("127.0.0.1");
/* ν¬νΈ λ²νΈλ 1435 */
sockaddr_internet.sin_port = htons(1435);
/* -------- 2 λ¨κ³ -------- */
/* μ€νΈλ¦Ό λ°©μμΌλ‘ μΈν°λ· λ§μ μ μνκΈ° μν μμΌμ μμ± */
sock = socket(AF_INET, SOCK_STREAM, 0);
/* μμΌ λ§λ€κΈ°μ μ€ν¨ μ INVALID_SOCKETμ΄ λ°ν */
if(sock == INVALID_SOCKET) printf("Invalid Socket");
/* -------- 3 λ¨κ³ -------- */
connection = connect(sock, sockaddr_internet, sizeof(struct sockaddr_in));
if(connection == SOCKET_ERROR) printf("Socket Error");
4. μμΌ ν΅μ νλ‘κ·Έλλ° (μλ²): TCP νλ‘ν μ½
μ΄λ²μλ μλ²κ° λμ΄ μ μ μμ²μ λ°μλ€μ¬λ³΄κ² μ΅λλ€.
4.1 sockaddr_in ꡬ쑰체 μ€μ νκΈ°
sockaddr_in ꡬ쑰체 μ€μ μ ν΄λΌμ΄μΈνΈμ ν¬κ² λ€λ₯΄μ§ μμ΅λλ€. λ€λ§ μμ μ IP μ£Όμλ₯Ό λͺ μνμ§ μλλ€λ μ°¨μ΄κ° μμ΅λλ€.
/* μ¬μ© μ */
struct sockaddr_in sockaddr_internet;
/* μ£Όμ 체κ³λ‘μ IPv4λ₯Ό μ¬μ©νλ μΈν°λ·λ§μ μ μ */
sockaddr_internet.sin_family = AF_INET;
/* μ μν λμμ μ§μ νμ§ μμ */
serveraddr.sin_addr.s_addr = inet_addr(INADDR_ANY);
/* ν¬νΈ λ²νΈλ 1435 */
serveraddr.sin_port = htons(1435);
- INADDR_ANY: μλμΌλ‘ μ΄ μ»΄ν¨ν°μ μ‘΄μ¬νλ λμΉ΄λ μ€ μ¬μ©κ°λ₯ν λμΉ΄λμ IPμ£Όμλ₯Ό μ¬μ©νλΌλ μλ―Έμ λλ€. μλ² μμΌμ μμ±ν λ μ¬μ©ν©λλ€.
4.2 socket μμ±νκΈ°
λ€νΈμν¬μ μ μνκΈ° μν μμΌμ μμ±ν©λλ€. μ΄ μμ ν΄λΌμ΄μΈνΈ μΈ‘μμ μμ±ν λ°©μκ³Ό κ°μ΅λλ€.
/* μ¬μ© μ: μΈν°λ·μ μ μνμ¬ μ€νΈλ¦Ό λ°©μμΌλ‘ μ
μΆλ ₯νλ μμΌ μμ± */
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
/* μμΌ λ§λ€κΈ°μ μ€ν¨ μ INVALID_SOCKETμ΄ λ°ν */
if(sock == INVALID_SOCKET) printf("Invalid Socket");
4.3 μμ±ν μμΌμ μ μμ λ°λ μ©λλ‘ μ§μ
bind ν¨μλ μμ±λ μμΌμ μ§μ IP μ£Όμμ ν¬νΈ λ²νΈλ₯Ό μ°κ²°μμΌ μλ²μ© μμΌμΌλ‘ λ§λ€μ΄μ£Όλ μν μ ν©λλ€.
int bind(SOCKET s, const struct sockaddr * name, int namelen);
- s: μλ²μ©μΌλ‘ μ¬μ©ν μμΌμ λλ€.
- name: μκΈ° μμ μ sockaddr ꡬ쑰체μ λλ€.
- namelen: μ¬κΈ°μμλ sockaddr_in ꡬ쑰체μ ν¬κΈ°μ λλ€.
/* μ¬μ© μ */
int state;
state = bind(sock , (struct sockaddr *)&sockaddr_internet, sizeof(sockaddr_in));
if (state == SOCKET_ERROR) printf("Socket Error");
4.4 μ μμ΄ λ€μ΄μ¬λκΉμ§ λκΈ°
μλ²λ‘μ κ°μΆμ΄μΌ ν μ€λΉλ λͺ¨λ λλ¬μ΅λλ€. μ΄μ μλμ΄ μ μν λκΉμ§ κ³μ κΈ°λ€λ¦¬κΈ°λ§ νλ©΄ λ©λλ€. μ΄ μν μ νλ ν¨μλ listen() ν¨μμ λλ€.
int listen(SOCKET s, int backlog);
- s: μλ²μ©μΌλ‘ μ°λ μμΌμ λλ€.
- backlog: μ΅λ λκΈ°μ μμ ν΄λΉνλ μ μ κ°μ λλ€. μ΄ κ°μ κΈ°μ€μ λ°λ‘ μ ν΄μ§μ§ μμκ³ κ²½νμ μΌλ‘ 5 μ λλ©΄ μ λΉνλ€κ³ μλ €μ Έ μμ΅λλ€.
/* μ¬μ© μ: μ μμκ° λ€μ΄μ¬λκΉμ§ λ΄λΆμ μΌλ‘ 무ν루νλ₯Ό λ리며 κ³μ μ΄ λ¨κ³μμ λ¨Έλ¬Όκ² λ κ²μ
λλ€.
int state = listen(sock, 5);
/* listenλ μ€λ₯μ SOCKET_ERRORλ₯Ό λ°νν©λλ€. μ μμ 1λͺ
μ μ±κ³΅μ μΌλ‘ λ°μλ€μλ€λ©΄ 0μ΄ λ°νλ κ²μ
λλ€. */
if(state == SOCKET_ERROR) printf("Socket Error");
4.5 μμ μκ² μ μν μ μ μ sockaddr_in μ»κΈ°
μλ²λ‘ μ΄μ΄λκ³ μ μμ κΈ°λ€λ ΈμΌλ©΄ μμ μκ² λ€μ΄μ¨ μ μ κ° λꡬμΈμ§λ₯Ό μ νμκ° μμ΅λλ€. ν΄λΌμ΄μΈνΈκ° connect ν¨μλ‘ μμ μκ² μ μνλ©΄μ ν΄λΌμ΄μΈνΈ μμ μ sockaddr_in ꡬ쑰체μ λ΄μ©λ μλ²μκ² μ ν΄μ§λλ° μ΄ μν μ accept ν¨μμμ μνν©λλ€.
SOCKET accept(SOCKET s, struct sockaddr * addr, int * addrlen);
- s: μλ²μ©μΌλ‘ μ°κ³ μλ μμΌμ λλ€.
- addr: μ μ μ μ μ λν μ 보λ₯Ό μ μ₯ν sockaddr ꡬ쑰체 ν¬μΈν°μ λλ€.
- addrlen: μ μλ μ μ μ λν μ λ³΄κ° λͺ λ°μ΄νΈμΈμ§λ μ΄ λ³μλ₯Ό ν΅ν΄ μ»μ μ μμ΅λλ€.
λ°ν κ°μΌλ‘ μ μμ 1μΈμ λν μμΌμ΄ λ°νλ©λλ€.
/* μ¬μ© μ */
SOCKET sockClient;
struct sockaddr_in sockaddrClient;
int sockaddrSize = 0;
sockClient = accept(sock, (struct sockaddr *)&sockaddrClient, &sockaddrSize);
if(sockClient == INVALID_SOCKET) printf("Invalid Socket");
else printf("μ μμ IPλ %sμ΄κ³ ꡬ쑰체 ν¬κΈ°λ %dλ°μ΄νΈμ
λλ€.", inet_ntoa(sockaddrClient.sin_addr), sockaddrSize);
5. λ°μ΄ν° κ΅ν: TCP νλ‘ν μ½
5.1 λ°μ΄ν° κ΅ν: send(), recv()
μ΄μ μλ²μ ν΄λΌμ΄μΈνΈκ°μ μ°κ²° μμ μ λͺ¨λ λ§μ³€μ΅λλ€. μ΄μ 본격μ μΌλ‘ λ°μ΄ν°λ₯Ό κ΅νν΄λ³΄κ² μ΅λλ€. λ°μ΄ν°μ κ΅νμ μ μ‘μ λ΄λΉνλ sendμ μμ μ λ΄λΉνλ recv ν¨μλ‘ μνλ©λλ€.
int send(SOCKET s, const char * buf, int len, int flags);
int recv(SOCKET s, char * buf, int len, int flags);
- s: λ°μ΄ν°λ₯Ό μ£Όκ³ λ°μ λμμ λνλ΄λ μμΌμ λλ€.
- buf: μ£Όκ³ λ°μ λ°μ΄ν°κ° κΈ°λ‘λμ΄μκ±°λ κΈ°λ‘λ λ²νΌμ λλ€.
- len: λ²νΌμ ν¬κΈ°(λ°μ΄νΈ)μ λλ€.
- flags: μ‘μμ κ΄λ ¨ μ΅μ μ λλ€. νμ¬λ‘μλ 0μΌλ‘ ν΄λ 무방ν©λλ€.
5.2 λ°μ΄ν° κ΅ν μμ : send(), recv()
λ°μ΄ν°μ κ΅νμ μλ²μ ν΄λΌμ΄μΈνΈκ°μ μ°κ²° μμ μ λ§μΉ ν μ μ‘μ λ΄λΉνλ sendμ μμ μ λ΄λΉνλ recv ν¨μλ‘ μνλ©λλ€. λ°ν κ°μ μλλ°©μκ² μ€μ λ‘ μ‘μ λλ μμ ν λ°μ΄ν° λ°μ΄νΈ μλ‘ lenλ³΄λ€ μκ±°λ κ°μ μ μμ΅λλ€. μ μ‘ μ΄μ μ SOCKET_ERRORμ΄ λ°νλ©λλ€.
/* μ¬μ© μ */
/* μλλ°©μΌλ‘ λ³΄λΌ λ©μμ§ */
char message[] = "Hello, World!";
/* μλλ°©μκ²μ μ ν΄μ€λ λ©μμ§ */
char buffer[256];
// ... μμΌ μΈν
μλ΅
strcpy(buffer, message);
/* λ³΄λΌ λ */
printf("sending...\n");
status = send(sockServer, buffer, sizeof(buffer), 0);
if (status == SOCKET_ERROR) // μ μ‘ μ΄μ μ μμΌ λ«κ³ νλ‘κ·Έλ¨ μ’
λ£
{
printf("send Error.\n");
closesocket(sockServer);
return -1;
}
printf("sent.\n");
/* λ°μ λ */
printf("receiving...\n");
status = recv(sockServer, buffer, sizeof(buffer), 0);
if (status == SOCKET_ERROR)
{
printf("recv Error.\n");
closesocket(sockServer);
return -1;
}
printf("received.\n");
5.3 send/recv μ write/readν¨μμ μ°¨μ΄?
send/recv μ write/readν¨μλ κ±°μ μ μ¬νμ§λ§, μΌλΆ μ°¨μ΄κ° μμ΅λλ€.
UNIX/Linuxμμ λͺ¨λ μ₯μΉ/μμμ FILEμ΄κΈ°μ μμΌμ΄λ μμλ read/writeλΌλ μΈν°νμ΄μ€λ‘ μ μΆλ ₯μ μνν©λλ€(recv/sendλ μ¬μ©κ°λ₯). νμ§λ§ Windowsμμλ μμΌμ΄ FILEλ‘ κ΄λ¦¬λμ§ μκΈ°μ recv/sendλ§ μ¬μ©κ°λ₯ν©λλ€. μΆκ°λ‘ recv/sendλ μμΌ μ μ© μΈν°νμ΄μ€μ΄κΈ°μ λ€μ μΆκ° μ΅μ μ΄ λ λ£μ μ μμ΅λλ€.
read/write: the universal file descriptor functions working on all
- ssize_t read(int fd, void *buf, size_t count); (μν°κ°λ μ μ₯ν¨.)
- ssize_t write(int fd, const void *buf, size_t count);
recv/send: work only on socket descriptors (socket μ μ©)
- ssize_t recv(int s, void *buf, size_t len, int flags);
- ssize_t send(int s, const void *buf, size_t len, int flags);
read()/write() is equivalent to recv()/send() with a flags parameter of 0(flags == 0)
6. μμΌ ν΅μ νλ‘κ·Έλλ° (ν΄λΌμ΄μΈνΈ, μλ²): UDP νλ‘ν μ½
μ΄λ²μλ μμ κ°μ΄ μμΌνλ‘κ·Έλλ°μ νλ UDP νλ‘ν μ½μΌ κ²½μ°, λ°κΏμΌ νλ ꡬμ±μ λν΄ μ€λͺ νλλ‘ νκ² μ΅λλ€. μμ κ±°μ λμΌνλ©° μΌλΆλ§ λ³κ²½λλ€λ μ μ κΈ°μ΅ν΄λμλ©΄ μ’μ κ² κ°μ΅λλ€.
6.1 μμΌ μμ±
ν΄λΌμ΄μΈνΈμ μλ² μμΌμ μμ±ν λ, SOCK_STREAMμΌλ‘ μμ±νλ κΈ°μ‘΄κ³Ό λ¬λ¦¬ SOCK_DGRAM μΌλ‘ μμ±ν©λλ€.
SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
6.2 μμΌμ μλ£ μ‘μμ
UDP/IP ν΅μ μμλ TCP/IPμλ λ¬λ¦¬ read()μ write()λ₯Ό μ¬μ©νμ§ μκ³ recvform()κ³Ό sendto()ν¨μλ₯Ό μ΄μ©νμ¬ μλ£λ₯Ό μ‘μμ ν©λλ€. sendto()ν¨μλ₯Ό λμ μ¬μ©νλ μ΄μ λ μ μ‘ν λͺ©μ μ§λ₯Ό μ§μ ν μ μκΈ° λλ¬Έμ΄λ©°, recvform()ν¨μλ₯Ό μ¬μ©νλ μ΄μ λ μμ λλ μλ£ μΈμλ μ‘μ μ§μ μ 보λ₯Ό ν¨κ» μ»μ μ μκΈ° λλ¬Έμ λλ€. κ·Έλ¬λ―λ‘ TCP/IPμ²λΌ νλ² μ°κ²°λλ©΄ μ°κ²°λ μμ€ν κ³Ό μλ£λ₯Ό μ£Όκ³ λ°μ§λ§ UDP/IPλ μμ λ‘κ² μμ€ν μ£Όμλ₯Ό λ°κΎΈμ΄ κ°λ©΄μ μλ£λ₯Ό μ‘μμ ν μ μμ΅λλ€.
6.2.1 μλ£ μ‘μ : sendto()
int sendto(SOCKET s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
- SOCKET s: μμΌ λμ€ν¬λ¦½ν°
- void *msg: μ μ‘ν λ°μ΄ν°
- size_t len: λ°μ΄ν°μ λ°μ΄νΈ λ¨μ κΈΈμ΄
- int flags: μ μ‘μ μν μ΅μ
- sockaddr *to: λͺ©μ μ§ μ£Όμ μ 보
- socklen_t tolen: λͺ©μ μ§ μ£Όμ μ 보μ ν¬κΈ°
6.2.2 sendto() μμ
uint32_t send_data;
struct sockaddr_in* local_addr_p = &local_addr;
if( (sock_fd != -1) && local_addr_p)
{
const char *sendMsg = "shuffle";
send_data = sendto(sock_fd, sendMsg, strlen(sendMsg), 0, (struct sockaddr*)local_addr_p, sizeof(local_addr));
if(send_mbr != strlen(sendMsg))
{
printf("sendto failure : ret(%u) slen(%d)\n", send_data, strlen(sendMsg) + 1);
}
}
6.2.3 μλ£ μμ : recvform()
int recvfrom(SOCKET s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)β
- SOCKET s: μμΌ λμ€ν¬λ¦½ν°
- void *buf: μλ£ μμ μ μν λ²νΌ ν¬μΈν°
- size_t len: λ²νΌμ λ°μ΄νΈ λ¨μ κΈΈμ΄
- int flags: μμ μ μν μ΅μ
- sockaddr *from: μ μ‘ν κ³³μ μ£Όμ μ 보
- socklen_t fromlen: μ μ‘ν μ£Όμ μ 보μ ν¬κΈ°
6.2.4 recvform() μμ
state = bind(sock, (struct sockaddr*)&sockaddr_internet, sizeof(sockaddr_in));
while(1)
{
int clntLen = sizeof(clntAddr);
int recvLen = recvfrom(sock, recvBuf, BUFSIZE, 0, (struct sockaddr*)&clntAddr, (socklen_t *)&clntLen)
if(recvLen == -1)
{
printf("recvfrom failed\n");
break;
}
else if (recvLen > 0)
{
...
μμ λ°μ΄ν° μ²λ¦¬
...
}
}
μ°Έκ³
- [Blog] μμΌ(SOCKET)ν΅μ μ΄λ?: https://helloworld-88.tistory.com/215
- [Blog] μμΌ ν΅μ #1 - μμΌ ν΅μ μ μ°μ΄λ ꡬ쑰체: https://tapito.tistory.com/381
- [Blog] μμΌ ν΅μ #2 - AF_INET μ¬μ©νκΈ°: https://tapito.tistory.com/382
- [StackOverFlow] What is the Difference Between read() and recv() , and Between send() and write()?: https://stackoverflow.com/questions/1790750/what-is-the-difference-between-read-and-recv-and-between-send-and-write
'Study: ComputerScience(CS) > CS: Network' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
[Network] C/C++μμ νλ‘μΈμ€ κ° ν΅μ (0) | 2023.01.17 |
---|---|
[Network] νλ‘μΈμ€ κ° ν΅μ λ°©λ²: IPC(Inter Process Communication) (0) | 2023.01.08 |
[Network] Message Queue(λ©μμ§ν) μ 리 (0) | 2022.11.26 |
[Network] λ€νΈμν¬ κΈ°λ³Έ κ°λ μ 리 (IP, Route, Subnet...) (1) | 2022.10.08 |
[Network] Blocking vs Non-Blocking & Sync vs Async λΉκ΅ μ 리 (0) | 2022.09.25 |