구매품목 : Keyboard. 

구매시기 : 2011.04.15

구매가격 : 10000원 


'News > Computer & etc.' 카테고리의 다른 글

DELL STUDIO 1558 i7-740QM 8G  (0) 2012.02.27
LENOVO ThinkPad i5-2520 6G x220 4286RS8  (0) 2012.02.27
DELL Monitor U2311H  (0) 2012.02.27
BK인포컴 NTY-EZ35HD[S-ATA/3.5형/USB/e-SATA]  (0) 2012.02.27
SAMSUNG 복합기 SCX-4623FK  (0) 2012.02.27

구매품목 : 외장하드케이스

구매가격 : 35,500

구매시기 : 2011.04.18



'News > Computer & etc.' 카테고리의 다른 글

DELL STUDIO 1558 i7-740QM 8G  (0) 2012.02.27
LENOVO ThinkPad i5-2520 6G x220 4286RS8  (0) 2012.02.27
DELL Monitor U2311H  (0) 2012.02.27
DELL Keyboard SK-8115  (0) 2012.02.27
SAMSUNG 복합기 SCX-4623FK  (0) 2012.02.27


'News > Computer & etc.' 카테고리의 다른 글

DELL STUDIO 1558 i7-740QM 8G  (0) 2012.02.27
LENOVO ThinkPad i5-2520 6G x220 4286RS8  (0) 2012.02.27
DELL Monitor U2311H  (0) 2012.02.27
DELL Keyboard SK-8115  (0) 2012.02.27
BK인포컴 NTY-EZ35HD[S-ATA/3.5형/USB/e-SATA]  (0) 2012.02.27

UDP/IP는 TCP/IP 처럼 클라이언트와 서버로 나뉘고 1 대 다수의 통신 방식은 아닙니다. 그냥 목적 시스템으로 자료를 전송하면 되는데, 문제는 UDP/IP를 이용하여 자료를 수신 받아야 하는 쪽은 받을 준비를 해야 합니다.

뭐, 당연한 말 아니냐? 하시겠습니다만 socket 을 만들었다고 socket을 통해 자료를 받을 수 없습니다. 생성한 socket을 커널에 올려 놓아야 커널이 socket 을 이용하여 상대방으로부터 전송된 데이터를 수신할 수 있습니다. 그러므로 처음 통신을 할 때, 자료 수신을 먼저 해야 하는 곳은 받드시 bind()를 사용해야 합니다.

UDP/IP 통신 함수 사용 순서

UDP/IP 통신에서는 TCP/IP와는 달리 read()와 write()를 사용하지 않고 recvform()과 sendto()함수를 이용하여 자료를 송수신합니다. sendto()함수를 대신 사용하는 이유는 전송할 목적지를 지정할 수 있기 때문이며, recvform()함수를 사용하는 이유는 수신되는 자료 외에도 송신지의 정보를 함께 얻을 수 있기 때문입니다.

그러므로 TCP/IP처럼 한번 연결되면 연결된 시스템과 자료를 주고 받지만 UDP/IP는 자유롭게 시스템 주소를 바꾸어 가면서 자료를 송수신 할 수 있습니다.

책에서는 TCP/IP를 전화기로 UDP/IP는 우체통으로 비유하는 경우가 많습니다. 우체통으로 비유한 만큼 UDP/IP는 우체통 하나로 여러 사람과 편지를 교환하듯 소켓 하나로 자유롭게 여러 시스템에게 자료를 송/수신할 수 있습니다.

또한 UDP/IP에서도 connect() 함수를 사용하여 read()와 write() 함수를 사용할 수 있습니다. 그러나 여기서는 다루지 않겠습니다.

UCP/IP 예제 소개

평상 시에도 자료를 수신할 수 있는 프로그램과 자료 전송만을 준비한 프로그램으로 나누어 올려 보겠습니다.

  1. 두 프로그램 모두 port 4000번을 사용하며
  2. 자료를 먼저 송신하는 쪽에서 임의의 문자를 전송하면
  3. 수신하는 쪽은 수신된 자료를 겹쳐서 전송하고
  4. 다시 송신하는 쪽에서 수신한 후 수신된 자료를 화면에 출력하겠습니다.

자료 수신 프로그램

자료 수신이 가능한 프로그램의 함수 사용 순서는 아래와 같습니다.

우선 socket 부터 만들어야 합니다. TCP/IP에서는 SOCK_STREAM을 UDP/IP에서는 SOCK_DGRAM을 사용하는 것을 참고하여 주십시오.

int     sock;

sock = socket( PF_INET, SOCK_DGRAM, 0); 
if (-1 == sock)
{
   printf( "socket 생성 실패"); 
   exit( 1) ;
}

bind() 함수를 이용하여 커널에 등록합니다.
  1. 만들어진 sock 은 단지 socket 디스크립터일 뿐입니다.
  2. 이 socket에 주소를 할당하고 port 번호를 할당해서 커널에 등록해야 합니다.
  3. 커널에 등록하면 클라이언트로부터 자료를 수신할 수 있는 귀를 달아 놓는 상태가 됩니다.
  4. socket에 주소와 port 를 할당하기 위해 sockaddr_in 구조체를 이용합니다.
  5. struct sockaddr_in server_addr;

    memset( &server_addr, 0, sizeof( server_addr);
    server_addr.sin_family      = PF_INET;                   // IPv4 인터넷 프로토롤 
    server_addr.sin_port        = htons( 4000);              // 사용할 port 번호는 4000
    server_addr.sin_addr.s_addr = htonl( INADDR_ANY);        // 32bit IPV4 주소

    if( -1 == bindsock, (struct sockaddr*)&server_addr, sizeof( server_addr) ) )
    {
       printf( "bind() 실행 에러n");
       exit( 1);
    }

  6. htonlINADDR_ANY) 는 주소를 지정해 주는 것으로 inet_addr( "내 시스템의 IP ")로도 지정할 수 있습니다. 그러나 프로그램이 실행되는 시스템 마다 IP 가 다를 것이므로 주소 지정을 고정 IP로 하지 않고 htonlINADDR_ANY) 를 사용하는 것이 편리합니다.

이제 socket 을 커널에 등록했으므로 recvfrom() 또는 sendto()를 이용하여 자료를 송수신할 수 잇습니다. recvfrom() 함수를 이용하여 클라이언트로부터 전송되어 오는 자료를 읽어 들입니다. 

  1. recvfrom()을 이용하여 송신 측의 주소 정보를 받아 오기 위해 변수를 선언합니다.
  2. struct sockaddr_in client_addr;
    int                client_addr_size;

  3. recvfrom()으로 자료를 수신합니다.
  4. client_addr_size = sizeof( client_addr);
    recvfromsock, buff_rcv, BUFF_SIZE, 0 , 
                ( struct sockaddr*)&client_addr, (socklen_t*)&client_addr_size);

  5. 수신한 자료가 있다면 자료는 buff 에 저장되며, client_addr에 송신측의 주소 정보가 담기게 됩니다.
  6. client_addr를 이용하여 송신한 측으로 자료를 전송할 수 있습니다.
sendto() 함수를 이용하여 데이터를 전송합니다. 

  1. 전송 데이터를 준비합니다.
  2. sprintf( buff_snd, "%s%s", buff_rcv, buff_rcv);

  3. sendto() 를 이용하여 클라이언트로 자료를 송신합니다.

    sendtosock, buff_snd, strlen( buff_snd)+1, 0, 
             ( struct sockaddr*)&client_addr, sizeof( client_addr)); // +1: NULL까지 포함해서 전송

  4. 위의 작업을 반복합니다.

자료 전송 프로그램

자료를 전송하는 쪽은 bind() 함수를 사용할 필요가 없으며, bind()함수를 사용하지 않았기 때문에 다른 시스템에서 전송하여도 전송 사실 자체를 알 수가 없습니다. 바로 설명 들어갑니다.

socket() 을 이용하여 소켓을 먼저 생성합니다.

int    sock;

sock= socket( PF_INET, SOCK_DGRAM, 0);
if( -1 ==sock)
{
   printf( "socket 생성 실패n");
   exit( 1);
}

컨널에 socket 을 등록할 필요 없이 sendto()로 자료를 송신할 수 있습니다. 

  1. 상대 시스템이 실행 중인지는 모릅니다. 그러나 전송할 수 있습니다.
  2. 상대 시스템의 주소 정보를 준비합니다.
  3. struct sockaddr_in server_addr;

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

  1. sendto() 함수로 데이터를 전송합니다.

    sendto( sock, argv[1], strlen( argv[1])+1, 0, 
             ( struct sockaddr*)&server_addr, sizeof( server_addr)); // +1: NULL까지 포함해서 전송

sendto() 함수를 사용하여 커널에 소켓이 등록되므로, 이번에는 recvfrom() 함수를 이용하여 상대로부터 자료를 읽어 들일 수 있습니다.
  1. recvfrom()을 이용하여 송신 측의 주소 정보를 받아 오기 위해 변수를 선언합니다.
  2. struct sockaddr_in server_addr;
    int                server_addr_size;

  3. recvfrom()으로 자료를 수신합니다.
  4. server_addr_size= sizeof(server_addr);
    recvfromsock, buff_rcv, BUFF_SIZE, 0 , 
                ( struct sockaddr*)&server_addr

    (socklen_t*)&server_addr_size);
  5. 수신한 자료가 있다면 자료는 buff 에 저장됩니다.
  1. 수신된 자료를 화면에 출력하고 종료합니다. 

    printf( "receive: %sn", buff_rcv);
    close( sock);
    return 0;

자료를 수신하는 쪽의 프로그램 소스

#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  BUFF_SIZE   1024

int   main( void)
{
   int   sock;
   int   client_addr_size;

   struct sockaddr_in   server_addr;
   struct sockaddr_in   client_addr;

   char   buff_rcv[BUFF_SIZE+5];
   char   buff_snd[BUFF_SIZE+5];



   sock  = socket( PF_INET, SOCK_DGRAM, 0);
   
   if( -1 == sock)
   {
      printf( "socket 생성 실패n");
      exit( 1);
   }

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

   if( -1 == bind( sock, (struct sockaddr*)&server_addr, sizeof( server_addr) ) )
   {
      printf( "bind() 실행 에러n");
      exit( 1);
   }

   while( 1)
   {
      client_addr_size  = sizeof( client_addr);
      recvfrom( sock, buff_rcv, BUFF_SIZE, 0 , 
                     ( struct sockaddr*)&client_addr, &client_addr_size);
      printf( "receive: %sn", buff_rcv);
      
      sprintf( buff_snd, "%s%s", buff_rcv, buff_rcv);
      sendto( sock, buff_snd, strlen( buff_snd)+1, 0,  // +1: NULL까지 포함해서 전송
                     ( struct sockaddr*)&client_addr, sizeof( client_addr)); 
} }

자료를 송신하는 쪽의 프로그램 소스

#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  BUFF_SIZE   1024

int   main( int argc, char **argv)
{
   int   sock;
   int   server_addr_size;

   struct sockaddr_in   server_addr;

   char   buff_rcv[BUFF_SIZE+5];


   sock  = socket( PF_INET, SOCK_DGRAM, 0);
   
   if( -1 == sock)
   {
      printf( "socket 생성 실패n");
      exit( 1);
   }

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

   sendto( sock, argv[1], strlen( argv[1])+1, 0,    // +1: NULL까지 포함해서 전송
            ( struct sockaddr*)&server_addr, sizeof( server_addr));          

   server_addr_size  = sizeof( server_addr);
   recvfrom( sock, buff_rcv, BUFF_SIZE, 0 , 
            ( struct sockaddr*)&server_addr, &server_addr_size);
   printf( "receive: %sn", buff_rcv);
   close( sock);
   
   return 0;
}

'Tips & Tech > Network' 카테고리의 다른 글

TCP/IP 프로그래밍 방법  (0) 2012.02.27
블록되지 않고 TCP 통신하려면...  (0) 2012.02.27

TCP/IP 통신 함수 사용 순서

TCP/IP 예제 소개

  TCP/IP 예제를 서버와 클라이언트로 나누어서 설명을 드리도록 하겠습니다.

  1. 서버와 클라이언트는 port 4000번을 사용
  2. 클라이언트프로그램에서 서버에 접속하면 실행할 때 입력받은 문자열을 전송
  3. 서버는 클라이언트로부터 자료를 수신하면 문자열 길이와 함께 수신한 문자열을 클라이언트로 전송

서버 프로그램

  서버 프로그램에서 사용해야할 함수와 순서는 아래와 같습니다.

  우선 socket 부터 만들어야 합니다. TCP/IP에서는 SOCK_STREAM을 UDP/IP에서는 SOCK_DGRAM을 사용하는 것을 참고하여 주십시오. socket()에 대한 더 자세한 말씀은 "Unix C Reference의 11장 7절 소켓 열고 닫기"를 참고하십시오.

int     server_socket;

server_socket = socket( PF_INET, SOCK_STREAM, 0); 
if (-1 == server_socket)
{
   printf( "server socket 생성 실패"); 
   exit( 1) ;
}

  bind() 함수를 이용하여 socket에 server socket 에 필요한 정보를 할당하고 커널에 등록

  1. 만들어진 server_socket 은 단지 socket 디스크립터일 뿐입니다.
  2. 이 socket에 주소를 할당하고 port 번호를 할당해서 커널에 등록해야 합니다.
  3. 커널에 등록해야 다른 시스템과 통신할 수 있는 상태가 됩니다.
  4. 더 정확히 말씀드린다면 커널이 socket 을 이용하여 외부로부터의 자료를 수신할 수 있게 됩니다.
  5. socket에 주소와 port 를 할당하기 위해 sockaddr_in 구조체를 이용합니다.
  6. struct sockaddr_in server_addr;

    memset( &server_addr, 0, sizeof( server_addr);
    server_addr.sin_family      = PF_INET;              // IPv4 인터넷 프로토롤 
    server_addr.sin_port        = htons( 4000);         // 사용할 port 번호는 4000
    server_addr.sin_addr.s_addr = htonl( INADDR_ANY);   // 32bit IPV4 주소

    if( -1 == bindserver_socket, (struct sockaddr*)&server_addr, sizeof( server_addr) ) )
    {
       printf( "bind() 실행 에러n");
       exit( 1);
    }

  7. htonlINADDR_ANY) 는 주소를 지정해 주는 것으로 inet_addr( "내 시스템의 IP ")로도 지정할 수 있습니다. 그러나 프로그램이 실행되는 시스템 마다 IP 가 다를 것이므로 주소 지정을 고정 IP로 하지 않고 htonlINADDR_ANY) 를 사용하는 것이 편리합니다.

  이제 listen() 함수로 클라이언트 접속 요청을 확인합니다. 

if( -1 == listen( server_socket, 5))
{
    printf( "대기상태 모드 설정 실패n");
    exit( 1);
}

  1. listen() 함수를 호출하면 클라이언트의 접속 요청이 올 때 까지 대기 상태가 됩니다. 즉, 블록된 모습이 되죠.
  2. 함수가 리턴이 되었을 때에는 클라이언트의 접속이 요청 되었다든지, 아니면 에러가 발생했을 경우입니다.
  3. 에러 없이 함수가 복귀했다면 클라이언트의 접속 요청입니다.
  4. 접속 요청을 허락합니다. 

  클라이언트 접속 요청에 따라 accept()로 접속을 허락합니다. 

  1. accept()로 접속 요청을 허락하게 되면 클라이언트와 통신을 하기 위해서 커널이 자동으로 소켓을 생성합니다.
  2. 이 소켓을 client socket이라고 하겠습니다.
  3. client socket 정보를 구하기 위해 변수를 선언합니다.  그리고 client 주소 크기를 대입합니다. 
  4. int     client_addr_size;

    client_addr_size = sizeof( client_addr);

  5. accept()를 호출 후에 에러가 없으면 커널이 생성한 client socket 을 반환해 줍니다.
  6. client_socket = accept( server_socket, (struct sockaddr*)&client_addr,
                                                              &client_addr_size);

    if ( -1 == client_socket)
    {
       printf( "클라이언트 연결 수락 실패n");
       exit( 1);
    }

  이제 client socket까지 만들어 졌으므로 read(), write() 함수를 이용하여 자료를 송수신 할 수 있습니다. read() 함수를 이용하여 클라이언트로부터 전송되어 오는 자료를 읽어 들입니다.

read ( client_socketbuff_rcv, BUFF_SIZE);

  1. read() 를 이용하여 클라이언트로부터 전송된 자료를 읽어 들입니다.
  2. 만일 클라이언트로부터 전송된 자료가 없다면 송신할 때 까지 대기하게 됩니다. 즉, 블록된 모습이 됩니다.
  이번에는 wirte() 함수를 이용하여 클라이언트도 데이터를 전송합니다. 

  1. 수신된 데이터의 길이를 구하여 전송 데이터를 준비합니다.
  2. sprintf( buff_snd, "%d : %s", strlen( buff_rcv), buff_rcv);

  3. write() 를 이용하여 클라이언트로 자료를 송신합니다.

    write( client_socketbuff_snd, strlen( buff_snd)+1); // +1: NULL까지 포함해서 전송

  작업이 완료되면 close() 를 이용하여 client socket 을 소멸 시켜 데이터 통신을 종료합니다.

closeclient_socket);

클라이언트 프로그램

  클라이언트 프로그램은 서버에 비해 간단합니다. 바로 설명 들어갑니다.

  socket() 을 이용하여 소켓을 먼저 생성합니다.

int     client_socket;

client_socket = socket( PF_INET, SOCK_STREAM, 0);
if( -1 == client_socket)
{
   printf( "socket 생성 실패n");
   exit( 1);
}

  connect()를 이용하여 서버로 접속을 시도합니다. 

  1. 주소 정보에 서버의 주소와 포트번호를 지정하고
  2. 서버와의 연결을 시도합니다.
  3. 예제에서는 시스템 자기를 가르키는 IP, 127.0.0.1 을 사용했습니다.
  4. struct sockaddr_in    server_addr;

    memset( &server_addr, 0, sizeof( server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons( 4000);
    server_addr.sin_addr.s_addr= inet_addr( "127.0.0.1");  // 서버의 주소

    if( -1 == connect( client_socket, (struct sockaddr*)&server_addr, sizeof( server_addr) ) )
    {
       printf( "접속 실패n");
       exit( 1);
    }

  1. 접속에 성공하면 데이터를 전송합니다.
  2. writeclient_socket, argv[1], strlen( argv[1])+1); // +1: NULL까지 포함해서 전송

  3. 자료를 수신하고 화면에 출력합니다.
  4. read ( client_socket, buff, BUFF_SIZE);
    printf( "%sn", buff);

  5. socket 을 소멸하여 통신 작업을 완료합니다.
  6. closeclient_socket);

서버 프로그램 소스

#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  BUFF_SIZE   1024

int   main( void)
{
   int   server_socket;
   int   client_socket;
   int   client_addr_size;

   struct sockaddr_in   server_addr;
   struct sockaddr_in   client_addr;

   char   buff_rcv[BUFF_SIZE+5];
   char   buff_snd[BUFF_SIZE+5];



   server_socket  = socket( PF_INET, SOCK_STREAM, 0);
   if( -1 == server_socket)
   {
      printf( "server socket 생성 실패n");
      exit( 1);
   }

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

   if( -1 == bind( server_socket, (struct sockaddr*)&server_addr, sizeof( server_addr) ) )
   {
      printf( "bind() 실행 에러n");
      exit( 1);
   }

   while( 1)
   {
      if( -1 == listen(server_socket, 5))
      {
         printf( "대기상태 모드 설정 실패n");
         exit( 1);
      }

      client_addr_size  = sizeof( client_addr);
      client_socket     = accept( server_socket, (struct sockaddr*)&client_addr, &client_addr_size);

      if ( -1 == client_socket)
      {
         printf( "클라이언트 연결 수락 실패n");
         exit( 1);
      }

      read ( client_socket, buff_rcv, BUFF_SIZE);
      printf( "receive: %sn", buff_rcv);
      
      sprintf( buff_snd, "%d : %s", strlen( buff_rcv), buff_rcv);
      write( client_socket, buff_snd, strlen( buff_snd)+1);          // +1: NULL까지 포함해서 전송
      close( client_socket);
   }
}

클라이언트 프로그램 소스

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

#include "sample.h"

#define  BUFF_SIZE   1024

int   main( int argc, char **argv)
{
   int   client_socket;

   struct sockaddr_in   server_addr;

   char   buff[BUFF_SIZE+5];

   client_socket  = socket( PF_INET, SOCK_STREAM, 0);
   if( -1 == client_socket)
   {
      printf( "socket 생성 실패n");
      exit( 1);
   }

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

   if( -1 == connect( client_socket, (struct sockaddr*)&server_addr, sizeof( server_addr) ) )
   {
      printf( "접속 실패n");
      exit( 1);
   }
   write( client_socket, argv[1], strlen( argv[1])+1);      // +1: NULL까지 포함해서 전송
   read ( client_socket, buff, BUFF_SIZE);
   printf( "%sn", buff);
   close( client_socket);
   
   return 0;
}

'Tips & Tech > Network' 카테고리의 다른 글

UDP/IP 프로그래밍  (0) 2012.02.27
블록되지 않고 TCP 통신하려면...  (0) 2012.02.27

+ Recent posts