UDP 소켓 프로그래밍

이동욱

2021/08/09

Categories: 네트워크

UDP 소켓 프로그래밍


UDP


UDP 헤더


UDP 소켓


UDP 소켓의 특징

UDP 서버 클라이언트 모델


소켓 생성

socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
socket (AF_INET, SOCK_DGRAM, 0);

데이터 전송

#include <sys/types.h>
#include <sys/socket.h>

ssize_t sendto (
    int sockfd,
    const void *buf,
    size_t len,
    int flags,
    const struct sockaddr *dest_addr,
    socklen_t addrlen
    )
  • sockfd: 소켓의 파일 디스크립터
  • buf: 전송할 데이어가 저장되어 있는 곳의 첫 주소
  • len: 전송할 데이터의 최대 길이
  • flags: 부가적인 기능을 설정할 수 있는 플래그
  • dest_addr: 목적지 주소
  • addrlen: 목적지 주소 공간의 크기
소켓의 출발지 주소는 어떻게 설정하는가?
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <arpa/inet.h>

void error_proc(const char*);

int main(int argc, char *argv[]) {
  int my_sock, read_len, n_sent;
  char buff[BUFSIZ];
  struct sockaddr_in dest_addr;
  socklen_t addr_len;

  my_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

  if (my_sock == -1) error_proc("socket");
  memset(&dest_addr, 0, sizeof(dest_addr));
  dest_addr.sin_addr.s_addr = inet_addr(argv[1]);
  dest_addr.sin_family = AF_INET;
  dest_addr.sin_port = htons(atoi(argv[2]));
  addr_len = sizeof(dest_addr);

  while(1) {
    fgets(buff, BUFSIZ - 1, stdin);
    read_len = strlen(buff);
    n_sent = sendto(my_sock, buff, read_len, 0, (struct sockaddr *) &dest_addr,
addr_len);
    printf("%d bytes were sent. \n", n_sent);
  }
  return 0;
}

void error_proc(const char* str) {
  fprintf(stderr, "%s: %s \n", str, strerror(errno));
  exit(1);
}

“출발지 주소를 설정하지 않고 sendto 함수를 호출한 경우, 소켓에 자동으로 IP 주소와 포트번호가 할당된다.”

데이터 수신


#include <sys/types.h>
#include <sys/socket.h>

ssize_t recvfrom (
  int socketfd,
  void *buf,
  size_t len,
  int flags,
  struct sockaddr *src_addr,
  socklen_t *addrlen
)
  • sockfd: 소켓의 파일 디스크립터
  • buf: 수신할 데이어가 저장될 곳의 첫 주소
  • len: 수신할 데이터의 최대 길이
  • flags: 부가적인 기능을 설정할 수 있는 플래그
  • src_addr: 출발지 주소를 저장할 구조체의 주소
  • addrlen: 출발지 주소 공간의 크기

전송 프로그램이 sendto 함수의 인자로 전달하는 포트번호 = 수신 프로그램이 bind 함수의 인자로 전달하는 포트번호

소켓 생성(socket) -> 소켓에 주소 설정(bind) -> recvfrom 함수 호출(recvfrom)

수신 프로그램 예제

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>

void error_proc(const char*);

int main(int argc, char **argv) {
  int my_sock, read_len, n_recv, res;
  char buff[BUFSIZ];

  struct sockaddr_in src_addr, dest_addr;
  socklen_t addr_len;

  if (argc != 2) {
    fprintf(stderr, "usage: %s port", argv[0]);
    return 0;
  }

  my_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  if (my_sock == -1) error_proc("socket");

  memset(&src_addr, 0, sizeof(src_addr));
  src_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  src_addr.sin_family = AF_INET;
  src_addr.sin_port = htons(atoi(argv[1]));

  res = bind(my_sock, (struct sockaddr *)&src_addr, sizeof(src_addr));

  if (res == -1) error_proc("bind");

  addr_len = sizeof(dest_addr);

  while(1) {
    n_recv = recvfrom(my_sock, buff, BUFSIZ - 1, 0, (struct sockaddr *)&dest_addr, &addr_len);
  if (n_recv == -1) error_proc("recv_from");
  printf("%d bytes were recv. \n", n_recv);
  }
  return 0;
}

void error_proc(const char *str) {
  fprintf(stderr, "%s: %s\n", str, strerror(errno));
  exit(1);
}

전송 측 화면

수신측 화면

다수의 클라이언트 처리


connect 함수의 역할


참고 문헌


>> Home