TCP or UDP기반의 데이터 전송의 경계를 확인하여 보겠습니다

설명)
UDP에 비해 TCP의 장점은
   1. 신뢰할수있다
   2. 데이터 누락 처리가 가능하다
   3. 데이터 순서바낌처리가 가능하다
   4. 데이터 경계가 없다

등이 있습니다

여기에선 4 데이터 경계가 없는  TCP와 경계가 있는 UDP에 대헤서 살펴 보도록 하겠습니다

일단 아래 그림을 참고하여 TCP의 결과는


 

보낸 문자열을 서로 구분하지 않고 2개씩 3개씩 혹은 몰아서 한꺼번에 recv에서 수신버퍼로 처리가 가능합니다
데이터의 경계가 없어서 넘어온 데이터는 송신버퍼에 쌓인후 순서대로 수신버퍼로 보내지게 됩니다



하지만 UDP의 경우 아래 그림을 참고하시면

보내는 수신버퍼와 받는 송신버퍼가 1:1임을 알수있습니다
ABC를 보내고 DEF 를 보내면 ABC DEF가 아닌
ABC를 처리하고 DEF를 처리하게 됩니다

앞에서 구형하였던 TCP Echo client 와 server는 UDP의 이러한 점을 모방하여 구현해놓은것입니다 


1)TCP


TCP Client 소스

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>

void error_handling(char * message);

int main()
{
  int sock;
  int str_len,i;
  struct sockaddr_in serv_addr;
  
  char msg1[] = "Hello Everybody~";
  char msg2[] = "I am so Happy!";
  char message[10];

  sock =  socket(PF_INET, SOCK_STREAM, 0);
  if(sock == -1)
    error_handling("socket() error");

  memset(&serv_addr, 0sizeof(serv_addr));
  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
  serv_addr.sin_port =  htons(9190);

  if ( connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1)
    error_handling("connect() error");

  write(sock , msg1, strlen(msg1));
  write(sock , msg2, strlen(msg2));
  
  sleep(3);

  for(i=0;i<4;i++)
  {
    str_len = read(sock,message,sizeof(message)-1);
    message[str_len] = 0;
    printf("message from server : %s \n", message);
  }
  
  close(sock);
  return 0;
}

void error_handling(char * message)
{
  fputs(message, stderr);
  fputc('\n', stderr);
  exit(1);
}



 TCP Server

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#define BUFSIZE 100

void error_handling(char * message);

int main()
{
  int serv_sock;
  int clnt_sock;
  struct sockaddr_in serv_addr;
  struct sockaddr_in clnt_addr;
  int clnt_addr_size;
  char message[BUFSIZE];
  int str_len;

  serv_sock =  socket(PF_INET, SOCK_STREAM, 0);
  if(serv_sock == -1)
    error_handling("socket() error");

  memset(&serv_addr, 0sizeof(serv_addr));
  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  serv_addr.sin_port =  htons(9190);

  if(bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1)
    error_handling("bind() error");

  if(listen(serv_sock,5== -1)
    error_handling("listen() error");
  
  clnt_addr_size = sizeof(clnt_addr);
  clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);

  if(clnt_sock == -1)
    error_handling("accept() error");

  sleep(5);
  str_len = read(clnt_sock,message,BUFSIZE);
  write(clnt_sock, message, sizeof(message));

  close(clnt_sock);
  return 0;
}

void error_handling(char* message)
{
  fputs(message, stderr);
  fputc('\n', stderr);
  exit(1);
}


결과>>


데이터의 경계가 없이 9바이트(sizeof(serv_addr)) == -1)크기에 처리한 순서대로 전송되어온것을 확인 할 수 있습니다!


2)UDP

UDP Client

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>

#define BUFSIZE 30

void error_handling(char * message);

int main()
{
  int sock;
  int str_len,addr_size,i;
  char message[BUFSIZE];
  
  struct sockaddr_in serv_addr;
  struct sockaddr_in from_addr;
  
  char msg1[] = "Good";
  char msg2[] = "Afternoon";
  char msg3[] = "Everybody!";

  sock =  socket(PF_INET, SOCK_DGRAM, 0);
  if(sock == -1)
    error_handling("socket() error");

  memset(&serv_addr, 0sizeof(serv_addr));
  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
  serv_addr.sin_port =  htons(9190);

  sendto(sock , msg1, strlen(msg1),0,(struct sockaddr*)&serv_addr, sizeof(serv_addr));
  sendto(sock , msg2, strlen(msg2),0,(struct sockaddr*)&serv_addr, sizeof(serv_addr));
  sendto(sock , msg3, strlen(msg3),0,(struct sockaddr*)&serv_addr, sizeof(serv_addr));
  
  sleep(3);

  for(i=0;i<3;i++)
  {
    addr_size = sizeof(from_addr);
    str_len = recvfrom(sock,message,BUFSIZE,0,(struct sockaddr*)&from_addr, &addr_size);
    message[str_len] = 0;
    printf("서버로 부터 수신된 %d 차 메세지  : %s \n", i, message);
  }
  close(sock);
  return 0;
}

void error_handling(char * message)
{
  fputs(message, stderr);
  fputc('\n', stderr);
  exit(1);
}


UDP Server 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>

#define BUFSIZE 30

void error_handling(char * message);

int main()
{
  int serv_sock;
  char message[BUFSIZE];
  int str_len, num = 0;
  
  struct sockaddr_in serv_addr;
  struct sockaddr_in clnt_addr;
  int clnt_addr_size;
  
  serv_sock =  socket(PF_INET, SOCK_DGRAM, 0);
  if(serv_sock == -1)
    error_handling("socket() error");

  memset(&serv_addr, 0sizeof(serv_addr));
  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  serv_addr.sin_port =  htons(9190);

  if(bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1)
    error_handling("bind() error");

  sleep(5);
  
  while(1)
  {
    clnt_addr_size = sizeof(clnt_addr);
    sleep(1);
    str_len = recvfrom(serv_sock,message,BUFSIZE,0,(struct sockaddr*)&clnt_addr, &clnt_addr_size);
    printf("수신번호 : %d \n", num++);
    sendto(serv_sock , message, str_len,0,(struct sockaddr*)&clnt_addr, sizeof(clnt_addr));
  }
  return 0;
}

void error_handling(char* message)
{
  fputs(message, stderr);
  fputc('\n', stderr);
  exit(1);
}

 

결과>>



전송된 문자열을 보면 단어별로 의미에 맞게 끝을 확인 할 수 있게 전송되었음을 알수 있습니다

Posted by mantwo