Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- Kafka
- 2025
- struct
- fwrite()
- sizeof()
- fread()
- scanf()
- half-close
- 백준
- strlen()
- 자식
- 구조체
- EOF
- container
- ifdef
- signal
- 에라토스테네스의 체
- 필기
- 카운팅 정렬
- pack
- endif
- 정보처리기사
- handling
- DEBUG
- Wait
- fork
- fgets()
- 10989
- Docker
- 1929
Archives
- Today
- Total
팥빵 먹으면서 코딩하는 블로그
05-1.[Linux/Ubuntu] 네트워크 프로그래밍 - UDP기반 서버/클라이언트 본문
UDP 소켓의 특성과 동작원리
- UDP 소켓 데이터 송수신
- Flow control이 없음
- UDP 소켓은 SEQ, ACK과 같은 메세지를 전달하지않음
- 단, 그러므로 데이터 전송이 빠름
- 연결 설정과 연결 해제 과정이 없음
- 단, (안전성보다) 성능이 우선시 될 때 UDP를 사용한다.
- 송수신하는 데이터의 양은 작으면서 빈번한 전송이 필요한 경우 UDP가 훨씬 효율적
- Flow control이 없음
- TCP를 쓰든 UDP를 쓰든 IP는 반드시 거친다.
- 패킷 전송에 있어 UDP와 IP의 역할 : 목적지를 찾기 위해서 IP를 거친다.
- UDP 소켓에서 port 번호 참조해서 최종 응용 프로그램에 전달한다.
- 이건 TCP도 마찬가지
- UDP Header
- TCP와 달리 Source port와 Destination port번호밖에 없다. 이 두 가지를 가지고 응용 프로그램에 데이터를 전달한다.
- UDP의 데이터 송수신
- UDP는 연결 설정 과정이 없음
- TCP는 1대 1의 연결을 필요로 했다.
- 서버 소켓과 클라이언트 소켓의 구분이 없다.
- UDP 소켓 생성과 데이터 송수신 과정만 존재한다.
- 하나의 소켓으로 둘 이상의 호스트와 데이터 송수신이 가능함
- 그룹 통신: multicast, broadcast(14장)
- 하나의 소켓에서 여러 특정한 곳에 데이터를 뿌리는 특징을 가짐 -> UDP를 쓴다.
UDP 데이터 통신 과정
- UDP Server
- 데이터 수신을 먼저 수행
- revfrom() 함수를 먼저 호출
- bind() 함수는 무조건 호출해야 한다.
- 고정된 port번호를 사용해야 전송된 패킷을 수신할 수 있기 때문
- UDP Clienet
- 데이터 송신을 먼저 수행
- sendto() 함수를 먼저 호출
- bind() 함수를 호출하지 않아도 됨
- 자동으로 자신의 ip주소와 port번호를 할당받은 상황에서, 상대방의 ip주소와 port번호를 알면 client가 송신을 먼저 했을 때 수신받은 server는 이를 받고 송수신을 수행하면 된다.
- sendto() 함수 - client
- 데이터를 전송할 때마다(매 패킷마다) 목적지에 대한 정보를 전달해야 됨 : ip주소, port 번호
- flag는 사용하는 경우가 거의 없어 그냥 0으로 지정하면 된다.
#include <sys/socket.h>
ssize_t sendto(int sock, void *buf, size_t nbytes, int flags,
struct sockaddr* to, socklen_t addrlen);
-> 성공 시 전송된 바이트 수, 실패 시 -1 반환
- sock : 데이터 전송에 사용될 UDP 소켓 디스크립터
- buf : 전송할 데이터를 저장하고 있는 버퍼의 주소
- nbytes : 전송할 데이터의 크기
------------------여기까진 TCP의 write() 와 같음-----------------------
- flags : 옵션 지정에 사용, 지정할 옵션이 없으면 0 입력
- to : 목적지 주소 정보를 담고 있는 구조체 변수의 주소값
- addrlen: to로 전달될 구조체(sockaddr)의 크기
!buf는 전송할 데이터의 주소를 담고, to는 목적지 주소 정보의 주소를 담는다!
- revfrom() 함수 - server
- UDP소켓을 통해 전송된 데이터를 수신
- from: 발신지 주소 정보를 주소값으로 저장(보낼 사람의 주소 정보)
#include <sys/socket.h>
ssize_t recvfrom(int sock, void *buf, size_t nbytes, int flags,
struct sockaddr* from, socklen_t *addrlen);
-> 성공 시 수신한 바이트 수, 실패 시 -1 반환
- sock : 데이터 수신에 사용될 UDP 소켓 디스크립터
- buf : 데이터 수신에 사용될 버퍼의 주소값
- nbytes : 수신할 최대 바이트 수, buf의 크기를 넘을 수 없음
------------------여기까진 TCP의 read() 와 같음-----------------------
- flags : 옵션 지정에 사용, 지정할 옵션이 없으면 0 입력
- from : 발신지 주소 정보를 저장할 sockaddr 구조체 주소값
- addrlen : from으로 전달될 주소값의 구조체(sockaddr) 변수 크기
- 참고) 포인트 쓰는 이유
- 단순하게 값을 가져와야하기 때문 / c언어는 return값이 1개이다.
- malloc쓰면 아작난다.. malloc안쓰고 memset으로 초기화 꼭 해주기
UDP 기반의 에코 서버와 클라이언트
- UDP echo server
- 수신한 데이터의 전송지 정보(clnt_adr)를 참조하여 데이터를 전송(echo)한다.
- UDP echo client
- UDP는 데이터의 경계가 존재하기 때문에 한번의 recvfrom() 함수 호출을 통해 하나의 메세지를 완전히 읽어들임
- sendto() 함수 호출 시 자신의 IP주소와 Port번호가 자동으로 할당
- UDP의 클라이언트 프로그램에서는 자신의 주소정보를 할당하는 별도의 과정이 없음
- message[str_len] = 0 // 문자열 마지막에 null 추가(쓰레기값 방지)
netstat 명령어
- netstat 명령어
- 시스템의 네트워크 연결 목록(tcp, udp)을 보여주는 유틸리티
- 옵션
- -a : 현재 다른 PC와 연결되어 있꺼나 대기(listening)중인 모든 포트 번호를 확인
- -t : TCP Protocol
- -u : UDP Protocol
- -s : IP, ICMP, UDP 프로토콜별 상태를 보여줌
- -nap : 열려있는 모든 포트를 보여줌
- 참고)
- ex. char msg[] = "hi!" ->크기를 지정하지 않았으므로 sizeof 연산 했을 때 byte크기 = 4bytes (null값이 자동 추가)
- 단, 구조체를 보낼 땐 sizeof 연산이 맞다. 문자열에서 null을 제외한 값을 보낼 땐 strlen이 맞다.
UDP 소켓
- 데이터 경계가 존재하는 UDP 소켓
- TCP
- 송수신하는 데이터에는 경계가 존재하지 않음
- 데이터 송수신 과정에서 입출력 함수의 호출 횟수는 큰 의미 없음
- UDP
- 데이터 경계가 존재
- 전송 함수(sendto())의 호출 횟수와 수신 함수(revfrom())의 호출 횟수가 일치해야 함!
- TCP
- Connected UDP 소켓
- 기존 UDP 소켓과는 다르게 UDP 소켓에 목적지 IP와 port 번호를 등록하고, 데이터 전송 후 UDP 소켓에 등록된 목적지 정보를 삭제하는 과정을 거치지 않음.
- 단지 데이터를 전송한다.
- 이걸 쓰는 목적은 read(), write() 함수 호출하려고.
- 하나의 호스트와 장시간 데이터를 송수신할 때 사용
- 하나의 호스트와 장시간 송수신, 이럴 때 Connected UDP가 효율적이다.
- socket 디스크립터와 상대방 주소 정보 연결하기 위해 쓴다.
- client부분에서 connect를 사용한다.
- ex. connect(sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr)); // bind와 같다.
- write(sock, message, strlen(message));
- str_len=read(sock, message, sizeof(message)-1);
- 참고)
- sendto() 에서 void *buf -> 뭐든 다 보낼수 있단 뜻
- -> 어떤 데이터 타입을 보낼 수도 있고 특징적으론 구조체를 보낼수도 있다.
'study > NETWORK PROGRAMMING' 카테고리의 다른 글
06-1 [Linux/Ubuntu] 네트워크 프로그래밍 - TCP 기반 Half-close (0) | 2025.04.11 |
---|---|
05-2. [Linux/Ubuntu] 네트워크 프로그래밍 - 구조체 정렬 및 조건부 컴파일 옵션 (0) | 2025.04.04 |
04-1. [Linux/Ubuntu] 네트워크 프로그래밍 - TCP 기반 서버/클라이언트 (0) | 2025.03.28 |
03-1. [Linux/Ubuntu] 네트워크 프로그래밍 - 소켓 타입과 프로토콜 설정 (0) | 2025.03.21 |
02-1. [Linux/Ubuntu] 네트워크 프로그래밍 - 소켓의 이해 (0) | 2025.03.15 |