😎 κ³΅λΆ€ν•˜λŠ” μ§•μ§•μ•ŒνŒŒμΉ΄λŠ” μ²˜μŒμ΄μ§€?

[λ¦¬λˆ…μŠ€ λ„€νŠΈμ›Œν‚Ή ν”„λ‘œκ·Έλž˜λ°] UDP λ„€νŠΈμ›Œν¬ ν”„λ‘œκ·Έλž˜λ° λ³Έλ¬Έ

πŸ‘©‍πŸ’» IoT (Embedded)/Raspberry Pi

[λ¦¬λˆ…μŠ€ λ„€νŠΈμ›Œν‚Ή ν”„λ‘œκ·Έλž˜λ°] UDP λ„€νŠΈμ›Œν¬ ν”„λ‘œκ·Έλž˜λ°

μ§•μ§•μ•ŒνŒŒμΉ΄ 2024. 1. 30. 20:02
728x90
λ°˜μ‘ν˜•

<μ„œμ˜μ§„ λ‹˜μ˜ 사물인터넷을 μœ„ν•œ λ¦¬λˆ…μŠ€ ν”„λ‘œκ·Έλž˜λ° with λΌμ¦ˆλ² λ¦¬νŒŒμ΄ μ„œμ μ„ μ°Έκ³ ν•΄μ„œ μž‘μ„±ν•˜μ˜€μŠ΅λ‹ˆλ‹€ :-)>

 

⭐ μ†ŒμΌ“μ˜ 이용

UDP ν”„λ‘œν† μ½œμ€ λ°μ΄ν„°μ˜ 전솑 μ‹œ 신뒰성은 μ—†μ§€λ§Œ 속도가 λΉ λ₯΄κΈ° λ•Œλ¬Έμ— 일반적인 LAN ν™˜κ²½μ—μ„œ 많이 μ‚¬μš©

LAN μƒμ—μ„œλŠ” νŒ¨ν‚·μ˜ 뢄싀이 거의 μ—†λ‹€κ³  함

 

μ„œλ²„μ˜ 경우 bind() ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ 운영체제의 ν•΄λ‹Ή 포트둜 λ“€μ–΄μ˜€λŠ” μ„œλΉ„μŠ€λ₯Ό UDP μ„œλ²„μ—μ„œ μ‚¬μš©ν•  수 μžˆλ„λ‘ μ—°κ²°ν•΄μ€˜μ•Ό ν•œλ‹€

UDPμ„œλ²„μ™€ ν΄λΌμ΄μ–ΈνŠΈ λͺ¨λ‘ sendto() ν•¨μˆ˜λ₯Ό ν†΅ν•΄μ„œ λ°μ΄ν„°κ·Έλž¨μ„ 보내고, recvfrom) ν•¨μˆ˜λ₯Ό 톡해 λ°μ΄ν„°κ·Έλž¨μ„ μˆ˜μ‹ ν•œλ‹€

μ†ŒμΌ“ μ‚¬μš©μ΄ λλ‚˜λ©΄ close() ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ μ†ŒμΌ“μ„ λ‹«λŠ”λ‹€

 

μœ λ‹‰μŠ€μ—μ„œ 인터넷 톡신을 ν•˜κΈ° μœ„ν•΄μ„œλŠ” λ¨Όμ € μ†ŒμΌ“μ„ 생성해야 ν•˜λŠ”λ°, socket() ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•œλ‹€

ν˜ΈμΆœμ— μ„±κ³΅ν•˜λ©΄ μ†ŒμΌ“μ— λŒ€ν•œ 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό λ°˜ν™˜ν•˜κ³ , μ‹€νŒ¨ν•˜λ©΄ -1을 λ°˜ν™˜ν•œλ‹€

int socket(int domain, int type, int protocol);

domain : μ†ŒμΌ“μ˜ 톡신 방식

μΈν„°λ„·μœΌλ‘œ 톡신할 것인지, 내뢀적인 파일 μ‹œμŠ€ν…œμ„ μ΄μš©ν•΄ 톡신할 것인지

도메인 λ‚΄μš© λΉ„κ³ 
PF_INET, AF_INET IPv4 인터넷 ν”„λ‘œν† μ½œ μ‚¬μš©  
PF_INET6, AF_INET6 IPv6 인터넷 ν”„λ‘œν† μ½œ μ‚¬μš©  
PF_LOCAL, AF_LOCAL 같은 μœ λ‹‰μŠ€ μ‹œμŠ€ν…œ λ‚΄μ—μ„œ ν”„λ‘œμ„ΈμŠ€λΌλ¦¬ ν†΅μ‹ ν•œλ‹€ PF_UNIX, AF_UNIX
PF_PACKET, AF_PACKET μ €μˆ˜μ€€ μ†ŒμΌ“ μΈν„°νŽ˜μ΄μŠ€ μ‚¬μš© SOCKET_PACKET

PF : Protocol Family

AF : Address Family

 

type : μ†ŒμΌ“μ˜ 전솑 방식

μ†ŒμΌ“μ€ TCP, UDP λ₯Ό μ§€μ›ν•˜λ©°, IPλ₯Ό 직접 μ΄μš©ν•˜κ±°λ‚˜ 직접 ν”„λ‘œν† μ½œμ„ λ§Œλ“€ λ•Œ μ‚¬μš©ν•  수 μžˆλŠ” Raw μ†ŒμΌ“λ„ 지원

슀트림 μ†ŒμΌ“μ€ TCP 기반 μ‹ λ’°μ„± ν•„μš”ν•œ 톡신에 이용

λ°μ΄ν„°κ·Έλž¨ μ†ŒμΌ“μ€ UPD 기반 μ‹ λ’°μ„± μ—†λŠ” λΉ λ₯Έ 톡신에 이용

νƒ€μž… μƒμˆ˜ λ‚΄μš©
슀트림 μ†ŒμΌ“ SOCKET_STREAM μ—°κ²° 지ν–₯ν˜• TCP 기반
μ†ŒμΌ“ κ°„μ˜ μ—°κ²° ν›„ 데이터 전솑
λ°μ΄ν„°κ·Έλž¨ μ†ŒμΌ“ SOCKET_DGRAM λΉ„μ—°κ²°ν˜•μ˜ UDP 기반
μ†‘μˆ˜μ‹  μ‹œ 도착지 μ£Όμ†Œ ν•„μˆ˜
Raw μ†ŒμΌ“ SOCKET_RAW μ €μˆ˜μ€€ ν”„λ‘œν† μ½œ μ ‘κ·Ό
IP 계측을 μ΄μš©ν•˜λ©° ICMP, OSPF 등이 μ‚¬μš©λ¨

 

protocol : λ„€νŠΈμ›Œν¬ ν”„λ‘œν† μ½œ

보톡은 0의 값을 많이 μ‚¬μš©ν•¨ (각각의 νšŒμ‚¬λ³„λ‘œ λ‹€μ–‘ν•œ ν”„λ‘œν† μ½œ μ‚¬μš©ν–‡μ§€λ§Œ, 주둜 TCP/IPκ°€ μ‚¬μš©λ˜λŠ” 쀑)

 

⭐ μ„œλ²„λ₯Ό μœ„ν•œ bind() ν•¨μˆ˜

UDP μ„œλ²„λ₯Ό μƒμ„±ν•˜κΈ° μœ„ν•΄μ„œλŠ” bind() ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄μ„œ ν΄λΌμ΄μ–ΈνŠΈλ‘œλΆ€ν„° λ“€μ–΄μ˜€λŠ” μ„œλΉ„μŠ€λ₯Ό ν˜„μž¬μ˜ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ μ‚¬μš©ν•  수 μžˆλ„λ‘ ν•΄λ‹Ή 포트λ₯Ό μš΄μ˜μ²΄μ œμ— λ“±λ‘ν•˜λŠ” μž‘μ—…μ„ μˆ˜ν–‰ν•΄μ•Ό ν•œλ‹€

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

 

sockfd : socket() ν•¨μˆ˜λ₯Ό 톡해 λ°˜ν™˜λ°›μ€ μ†ŒμΌ“μ˜ 파일 λ””μŠ€ν¬λ¦½ν„°

*addr : UDP μ„œλ²„μ˜ μ£Όμ†Œ 정보

addrlen : μ£Όμ†Œ 크기

 

μœ λ‹‰μŠ€ λ‚΄λΆ€μ—μ„œ 톡신을 μ‚¬μš©ν•˜λŠ” 경우 socketaddr_un ꡬ쑰체λ₯Ό μ‚¬μš©ν•˜λ©° μ£Όμ†Œλ‘œ 파일 μœ„μΉ˜λ₯Ό μ‚¬μš©

λ„€νŠΈμ›Œν¬ 톡신을 μ‚¬μš©ν•˜λŠ” 경우 sockaddr_in ꡬ쑰체λ₯Ό μ‚¬μš©ν•˜λ©° μ„œλ²„μ˜ IP μ£Όμ†Œμ™€ 포트 번호λ₯Ό μ‚¬μš©

이 두 ꡬ쑰체λ₯Ό ν•˜λ‚˜λ‘œ ν†΅ν•©ν•˜λŠ” ꡬ쑰체가 sockaddr ꡬ쑰체

 

⭐ λ°”μ΄νŠΈ μˆœμ„œ λ³€ν™˜

λ„€νŠΈμ›Œν¬ μ„œλ²„λ‘œ 많이 μ‚¬μš©λ˜μ—ˆλ˜ SUN μ—μ„œ μ‚¬μš©ν•˜λŠ” RISC CPU 와 IBM PC μ—μ„œ μ‚¬μš©ν•˜λŠ” μΈν…”μ˜ x86 CPUλŠ” λ©”λͺ¨λ¦¬μ— 데이터λ₯Ό μ €μž₯ν•˜λŠ” 방식이 λ‹€λ₯΄λ‹€

 

μΈν…”μ˜ x86μ΄λ‚˜ DEC의 ν”„λ‘œμ„ΈμŠ€μ—μ„œ μ‚¬μš©ν•˜λŠ” 리틀 μ—”λ””μ•ˆ 방식이 κ°€μž₯ μž‘μ€ κ°’μ˜ λ°”μ΄νŠΈλΆ€ν„° λ¨Όμ € ν‘œμ‹œ 됨

16μ§„μˆ˜ 1A2B3C4D -> 4D3C2B1A

IBM 370 컴퓨터와 썬 λ§ˆμ΄ν¬λ‘œμ‹œμŠ€ν…œμ¦ˆμ˜ SPARC λ“± RISC λ°©μ‹μ˜ μ›Œν¬μŠ€ν…Œμ΄μ…˜μš© CPU듀은 λΉ… μ—”λ””μ•ˆ μ‚¬μš©

 

λ„€νŠΈμ›Œν¬μƒμ—μ„œλŠ” 순차적으둜 데이터가 μ „μ†‘λ˜λŠ”λ° λΉ… μ—”λ””μ•ˆμ΄ 더 μ ν•©ν•˜λ‹€

λ„€νŠΈμ›Œν¬ λ°”μ΄νŠΈ μˆœμ„œ (Network Byte Order) 은 솑/μˆ˜μ‹  데이터 λͺ¨λ‘ λΉ… μ—”λ””μ•ˆμœΌλ‘œ κ°„μ£Όν•΄μ„œ μ²˜λ¦¬ν•΄μ•Ό 함

 

PCμ—μ„œ μ‚¬μš©λ˜κ³  μžˆλŠ” CPUλŠ” 인텔 κ³„μ—΄μ˜ CPU 이기 λ•Œλ¬Έμ— μ—”λ””μ•ˆ λ³€ν™˜μ΄ ν•„μš”ν•  수 μžˆλŠ”λ°, μœ λ‹‰μŠ€λŠ” 호슀트 λ°”μ΄νŠΈ μˆœμ„œμ™€μ˜ λ³€ν™˜μ„ μœ„ν•œ λ‹€μ–‘ν•œ ν•¨μˆ˜λ“€μ„ μ œκ³΅ν•˜κ³  μžˆλ‹€

 

#include <arpa/inet.h>

uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

μ—”λ””μ•ˆ λ³€ν™˜ λ°©ν–₯μ—λŠ” hton λ°©ν–₯κ³Ό ntoh λ°©ν–₯이 μžˆλ‹€

hton 은 ν˜ΈμŠ€νŠΈμ—μ„œ λ„€νŠΈμ›Œν¬ λ°”μ΄νŠΈ μˆœμ„œ (host to network)

ntoh 은 λ„€νŠΈμ›Œν¬μ—μ„œ 호슀트 λ°”μ΄νŠΈ μˆœμ„œ (network to host)

μ ‘λ―Έμ–΄λŠ” λ³€ν™˜ 크기λ₯Ό λ‚˜νƒ€λ‹ˆλ©°, s λŠ” short(16λΉ„νŠΈ), l 은 long(32λΉ„νŠΈ)

 

IPv4의 IP μ£Όμ†ŒλŠ” 32λΉ„νŠΈμ΄λ―€λ‘œ htonl() ν•¨μˆ˜, 포트 λ²ˆν˜ΈλŠ” 16μ§„μˆ˜μ΄λ―€λ‘œ htons()

hλŠ” 호슀트, beλŠ” λΉ… μ—”λ””μ•ˆ, leλŠ” 리틀 μ—”λ””μ•ˆ

μˆ«μžλŠ” λΉ„νŠΈ 수

 

⭐ λ„€νŠΈμ›Œν¬ μ£Όμ†Œ λ³€ν™˜

λ„€νŠΈμ›Œν¬μ˜ μ£Όμ†ŒλŠ” IP μ£Όμ†Œ μ΄κ±°λ‚˜ 도메인 λ„€μž„

IP μ£Όμ†ŒλŠ” soctaddr_in ꡬ쑰체의 sin_addr ν•­λͺ©μ—μ„œ μ‚¬μš©ν•˜λŠ” 값은 16μ§„μˆ˜μ˜ μ •μˆ˜κ°’ μ΄λ―€λ‘œ 이 λ¬Έμžμ—΄μ„ 16μ§„μˆ˜λ‘œ λ³€ν™˜ν•œλ‹€

ν•¨μˆ˜ λ‚΄μš© λΉ„κ³ 
inet_pton() λ¬Έμžμ—΄ ν˜•νƒœμ˜ IPμ£Όμ†Œλ₯Ό 숫자 ν˜•νƒœμ˜ IP μ£Όμ†Œλ‘œ λ³€ν™˜ inet_aton() λ˜λŠ” inet_addr()
inet_ntop() 숫자 ν˜•νƒœμ˜ IPμ£Όμ†Œλ₯Ό λ¬Έμžμ—΄ ν˜•νƒœμ˜ IP μ£Όμ†Œλ‘œ λ³€ν™˜ inet_ntoa()
inet_network() IPμ£Όμ†Œλ₯Ό 호슀트 μˆœμ„œμ—μ„œ λ„€νŠΈμ›Œν¬ μˆœμ„œλ‘œ λ³€ν™˜ν•œλ‹€  

 

⭐ UDP λ°μ΄ν„°μ˜ μ†‘μˆ˜μ‹ 

TCP λŠ” μ„œλ²„κ°€ μ—°κ²°λ˜μ–΄ μžˆμœΌλ―€λ‘œ read() λ‚˜ write() 같은 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό μ‘°μž‘ν•˜λŠ” ν•¨μˆ˜λ₯Ό μ΄μš©ν•΄μ„œ 데이터 μ†‘μˆ˜μ‹ 

UDP λŠ” μ„œλ²„κ°€ μ—°κ²°λ˜μ–΄ μžˆμ§€ μ•ŠμœΌλ―€λ‘œ λ‹€λ₯Έ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•¨, sendto() ν•¨μˆ˜μ™€ recvfrom()

UDP λŠ” sendto() ν•¨μˆ˜μ— 데이터λ₯Ό 받을 μƒλŒ€λ°©μ˜ 정보 (μ£Όμ†Œμ™€ 포트번호)λ₯Ό μž…λ ₯ν•˜κ³  recvfrom() ν•¨μˆ˜λ₯Ό μ΄μš©ν•΄μ„œ 데이터λ₯Ό 보낸 μƒλŒ€λ°©μ˜ 정보λ₯Ό κ°€μ Έμ˜¬ 수 μžˆλ‹€

 

UDP μ—μ„œλ„ ν•˜λ‚˜μ˜ μ„œλ²„λ§Œ ν†΅μ‹ ν•˜λŠ” 경우라면 connect() ν•¨μˆ˜λ₯Ό μ΄μš©ν•΄μ„œ μ„œλ²„μ— μ ‘μ†ν•œ ν›„, μ§€μ •λœ μ£Όμ†Œμ™€ read()λ‚˜ write() ν•¨μˆ˜λ₯Ό 톡해 톡신을 μˆ˜ν–‰ν•  수 μžˆλ‹€

sendto() ν•¨μˆ˜λ‚˜ recvfrom() ν•¨μˆ˜λ“€μ€ 데이터λ₯Ό 주고받을 λ•Œ λ„€νŠΈμ›Œν¬λ₯Ό μ—°κ²°ν•˜κ³  μ²˜λ¦¬κ°€ λλ‚˜λ©΄ μ—°κ²°λœ λ„€νŠΈμ›Œν¬λŠ” λŠμ–΄μ§„λ‹€

connect() λ₯Ό μ΄μš©ν•˜λ©΄ λ„€νŠΈμ›Œν¬μ˜ 연결을 계속 μœ μ§€ν•˜κΈ° λ•Œλ¬Έμ— λΉ λ₯Έ μ†λ„λ‘œ μ œκ³΅ν•  수 μžˆλ‹€

 

⭐ λ°”μ΄νŠΈ μ‘°μž‘

λ„€νŠΈμ›Œν¬ ν”„λ‘œκ·Έλž˜λ―Έμ—μ„œλŠ” IPμ£Όμ†Œλ‚˜ 기타 처리λ₯Ό μœ„ν•΄ λ°”μ΄νŠΈ μ‘°μž‘μ΄ ν•„μš”ν•œ κ²½μš°κ°€ λ§Žλ‹€

λ°”μ΄νŠΈ μ‘°μž‘μ„ μœ„ν•΄ memset(), memcpy(), memcmp() λ“±μ˜ ν•¨μˆ˜κ°€ 제곡되며

BSD μœ λ‹‰μŠ€μ—μ„œ bzero(), bcopy(), bcmp() λ“±μ˜ ν•¨μˆ˜λ₯Ό μ œκ³΅ν•œλ‹€

 

memset() ν•¨μˆ˜λŠ” λ©”λͺ¨λ¦¬μ˜ λ°”μ΄νŠΈλ₯Ό νŠΉμ • κ°’μœΌλ‘œ μ„€μ •ν•  수 μžˆμ§€λ§Œ

λ„€νŠΈμ›Œν¬ μ£Όμ†Œμ™€ μ΄ˆκΈ°ν™”λŠ” 주둜 bzero() ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄μ„œ λ°”μ΄νŠΈλ₯Ό λͺ¨λ‘ 0으둜 μ„€μ •ν•œλ‹€

// udp_server.c
// μ†ŒμΌ“μ„ μ΄μš©ν•΄μ„œ UDP둜 μ„œλ‘œ ν†΅μ‹ ν•˜κΈ°
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>

#define UDP_PORT 5100

int main(int argc, char **argv)
{
    int sockfd,n;
    struct sockaddr_in servaddr, cliaddr;
    socklen_t len;
    char mesg[1000];

    sockfd = socket(AF_INET, SOCK_DGRAM, 0); 	/* UDPλ₯Ό μœ„ν•œ μ†ŒμΌ“ 생성 */

    /* μ ‘μ†λ˜λŠ” ν΄λΌμ΄μ–ΈνŠΈλ₯Ό μœ„ν•œ μ£Όμ†Œ μ„€μ • ν›„ μš΄μ˜μ²΄μ œμ— μ„œλΉ„μŠ€ 등둝 */
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(UDP_PORT);
    bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

    /* ν΄λΌμ΄μ–ΈνŠΈλ‘œλΆ€ν„° λ©”μ‹œμ§€λ₯Ό λ°›μ•„μ„œ λ‹€μ‹œ ν΄λΌμ΄μ–ΈνŠΈλ‘œ 전솑 */
    do {
        len = sizeof(cliaddr);
        n = recvfrom(sockfd, mesg, 1000, 0, (struct sockaddr *)&cliaddr, &len);
        sendto(sockfd, mesg, n, 0, (struct sockaddr *)&cliaddr, sizeof(cliaddr));
        mesg[n] = '\0';
        printf("Received data : %s\n", mesg);
    } while(strncmp(mesg, "q", 1));

    close(sockfd); 				/* μ‚¬μš©μ΄ λλ‚œ ν›„ μ†ŒμΌ“ λ‹«κΈ° */

    return 0;
}

/*
μ„œλ²„λŠ” ν΄λΌμ΄μ–ΈνŠΈλ‘œλΆ€ν„° 데이터λ₯Ό λ°›μ•„μ„œ κ·ΈλŒ€λ‘œ λ‹€μ‹œ λ˜λŒλ €μ£ΌλŠ” 에코 (ECHO) μ„œλ²„

socket() ν•¨μˆ˜μ— SOCK_DGRAM μ˜΅μ…˜μ„ μ‚¬μš©ν•΄μ„œ UDPλ₯Ό μœ„ν•œ μ†ŒμΌ“μ˜ 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό μ—°λ‹€
ν•΄λ‹Ή ν”„λ‘œκ·Έλž¨μ„ μ„œλ²„λ‘œ μ‚¬μš©ν•˜κΈ° μœ„ν•΄μ„œλŠ” μš΄μ˜μ²΄μ œμ— μ„œλΉ„μŠ€λ₯Ό 등둝해야 ν•œλ‹€ -> bind()
bind() ν•¨μˆ˜μ— sockaddr_in ꡬ쑰체λ₯Ό μ‚¬μš©ν•΄μ„œ μ„œλ²„μ˜ μ£Όμ†Œμ™€ 포트 번호λ₯Ό μ„€μ •ν•œλ‹€
μ„€μ •ν•˜κΈ° 전에 sockaddr_in ꡬ쑰체λ₯Ό memset() ν•¨μˆ˜λ₯Ό 톡해 0으둜 μ΄ˆκΈ°ν™”
μ„œλ²„μ˜ μ£Όμ†Œκ°€ λ™μ μœΌλ‘œ 바귀더라도 μ‚¬μš©ν•˜κΈ° 쉽도둝 INADDR_ANY μ‚¬μš©
htonl() 와 htons() ν•¨μˆ˜λ₯Ό μ΄μš©ν•΄μ„œ IP μ£Όμ†Œμ™€ 포트 번호λ₯Ό λ„€νŠΈμ›Œν¬ μˆœμ„œλ‘œ μ—”λ””μ•ˆ λ³€κ²½

루프문 λŒλ©΄μ„œ ν΄λΌμ΄μ–ΈνŠΈλ‘œλΆ€ν„° 데이터λ₯Ό λ°›κ³ , 받은 데이터λ₯Ό sendto() ν•¨μˆ˜λ₯Ό μ΄μš©ν•΄μ„œ λ‹€μ‹œ ν΄λΌμ΄μ–ΈνŠΈλ‘œ 전솑
ν΄λΌμ΄μ–ΈνŠΈμ—μ„œ λ¬Έμžμ—΄ 'q' κ°€ 였면 μ’…λ£Œ, λͺ¨λ“  μž‘μ—…μ΄ λλ‚˜λ©΄ close() ν•¨μˆ˜λ‘œ μ†ŒμΌ“ λ‹«κΈ°
*/
// udp_client.c
// μ†ŒμΌ“μ„ μ΄μš©ν•΄μ„œ UDP둜 μ„œλ‘œ ν†΅μ‹ ν•˜κΈ°
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define UDP_PORT 5100

int main(int argc, char **argv)
{
    int sockfd, n;
    socklen_t clisize;
    struct sockaddr_in servaddr, cliaddr;
    char mesg[BUFSIZ];

    if(argc != 2) {
        printf("usage : %s <IP address>\n", argv[0]);
        return -1;
    }

    sockfd = socket(AF_INET, SOCK_DGRAM, 0); 	/* UDPλ₯Ό μœ„ν•œ μ†ŒμΌ“ 생성 */

    /* μ„œλ²„μ˜ μ£Όμ†Œμ™€ 포트 번호λ₯Ό μ΄μš©ν•΄μ„œ μ£Όμ†Œ μ„€μ • */
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;

    /* λ¬Έμžμ—΄μ„ λ„€νŠΈμ›Œν¬ μ£Όμ†Œλ‘œ λ³€κ²½ */
    inet_pton(AF_INET, argv[1], &(servaddr.sin_addr.s_addr));
    servaddr.sin_port = htons(UDP_PORT);

    /* ν‚€λ³΄λ“œλ‘œλΆ€ν„° λ¬Έμžμ—΄μ„ μž…λ ₯λ°›μ•„ μ„œλ²„λ‘œ 전솑 */
    do {
        fgets(mesg, BUFSIZ, stdin);
        sendto(sockfd, mesg, strlen(mesg), 0, (struct sockaddr *)&servaddr,
        sizeof(servaddr));
        clisize = sizeof(cliaddr);

        /* μ„œλ²„λ‘œλΆ€ν„° 데이터λ₯Ό λ°›μ•„μ„œ 화면에 좜λ ₯ */
        n = recvfrom(sockfd, mesg, BUFSIZ, 0, (struct sockaddr*) &cliaddr, &clisize);
        mesg[n] = '\0';
        fputs(mesg, stdout);
    } while(strncmp(mesg, "q", 1));

    close(sockfd);

    return 0;
}

/*
ν”„λ‘œκ·Έλž¨μ„ μ‹«λž­ν•  λ•Œ 접속할 μ„œλ²„μ˜ μ£Όμ†Œλ₯Ό μž…λ ₯ν•˜λ©΄ λ˜λŠ”λ°
μž…λ ₯받은 λ¬ΈμžλŠ” inet_pton() ν•¨μˆ˜λ₯Ό μ΄μš©ν•΄μ„œ 16μ§„μˆ˜ μ£Όμ†Œλ‘œ λ³€ν™˜ν•  수 μžˆλ‹€

라즈베리파이둜 접속쀑이라면 μ„œλ²„λ₯Ό λ°±κ·ΈλΌμš΄λ“œ λͺ¨λ“œλ‘œ μ‹€ν–‰ν•œλ‹€ &
같은 라즈베리파이 μ•ˆμ—μ„œ UDP μ„œλ²„μ™€ ν΄λΌμ΄μ–ΈνŠΈλ₯Ό ν•¨κ»˜ μ‹€ν–‰ν•  λ•Œ μ„œλ²„ μ£Όμ†Œλ‘œ 127.0.0.1
127.0.0.1은 루프백 μ£Όμ†ŒλΌκ³ λ„ ν•˜λŠ”λ°, ν˜„μž¬ μ‹œμŠ€ν…œ 자체의 IP μ£Όμ†Œλ₯Ό 지칭할 λ•Œ μ‚¬μš©ν•œλ‹€

ν΄λΌμ΄μ–ΈνŠΈμ—μ„œ λ¬Έμžμ—΄μ„ μž…λ ₯ν•˜λ©΄ UDPλ₯Ό 톡해 ν΄λΌμ΄μ–ΈνŠΈμ™€ μ„œλ²„ κ°„ 톡신이 이뀄진닀
μ„œλ²„λŠ” μš΄μ˜μ²΄μ œμ—μ„œ λ„˜μ–΄μ˜¨ 데이터λ₯Ό λ°›μ•„μ„œ 화면에 좜λ ₯ν•œ λ’€ λ°”λ‘œ 좜λ ₯ν•˜κ³ 
λ‹€μ‹œ ν΄λΌμ΄μ–ΈνŠΈμ˜ μž…λ ₯을 κΈ°λ‹€λ¦°λ‹€
*/
gcc -o udp_server udp_server.c 
gcc -o udp_client udp_client.c 
./udp_server &
./udp_client 127.0.0.1

 

 

 

 

728x90
λ°˜μ‘ν˜•
Comments