C221-S3C6410 보드에 있는 Ehternet을 TCP로 데이터로 수신한 데이터를 RS232 Port로 전송하는 프로그램을 작성해 보도록 해 보겠습니다.

대략적인 구성도 저번 강좌의 C221-S3C6410 보드 활용기 [ RS232 to TCP ]와 같습니다.
 
 
tcptors232.jpg
 
 
Ethernet의 TCP로 들어온 데이타를 RS232 장비로 데이타를 보내는 간단한 프로그램 소스입니다.
 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <net/if.h>

#include <arpa/inet.h>
#include <sys/socket.h>

#include <termios.h>                   // B115200, CS8 등 상수 정의
#include <fcntl.h>                     // O_RDWR , O_NOCTTY 등의 상수 정의

 

#define BUFF_SIZE  1024
#define TCP_LISTEN_PORT 4000

 

int  fd_server;              // TCP 서버 소켙의 파일 디스크립터
int  fd_client;
int  fd_232;

struct  termios newtio;
struct  pollfd poll_events[2];             // TCP 서버 소켙과 클라이언트 소켙을 위해 2개 사용

 

void on_data()
{
     char buff_rcv[BUFF_SIZE+1];
     int  rd_cnt;

     rd_cnt = read ( fd_client, buff_rcv, BUFF_SIZE);     // 클라이언트로부터 전송된 메시지 수령
     if ( 0 < rd_cnt){
          write( fd_232, buff_rcv, rd_cnt);
     }
}

 

void on_accept()
{
      size_t sz_client_addr;
      struct sockaddr_in   client_addr;

 

      // 여기까지 실행되었다면 클라이언트로부터 접속 요청이 있었음
      // accept()로 클라이언트와 연결
      sz_client_addr  = sizeof( client_addr);
      fd_client  = accept( fd_server, (struct sockaddr *)&client_addr, &sz_client_addr);

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

 

      if ( 0 == poll_events[1].fd ) {
           poll_events[1].fd = fd_client;
      } else {
           close( fd_client);            // 클라이언트 소켓 사용 종료
      }
}

 

int main( int argc, char *argv[])
{
     if ( 2 > argc ) {
          printf( "인수가 모자릅니다. 시리얼 포트를 입력하여 주시오\n");
          printf( "실행방법: ]$ ./app_tcp_to_rs232 /dev/ttySAC3 \n");
          exit( 0);
     }

 

     // RS232 포트 open ////////////////////////////////////////////////////////////

     fd_232 = open( argv[1], O_RDWR | O_NOCTTY | O_NONBLOCK );        // 디바이스를 open 한다.   
     if ( 0 > fd_232 ) {
          printf("open error\n");
          return -1;
     }

 

     memset( &newtio, 0, sizeof(newtio) );
     newtio.c_cflag       = B115200 | CS8 | CLOCAL | CREAD;
     newtio.c_oflag       = 0;
     newtio.c_lflag       = 0;
     newtio.c_cc[VTIME]   = 0;
     newtio.c_cc[VMIN]    = 1;

     tcflush  (fd_232, TCIFLUSH );
     tcsetattr(fd_232, TCSANOW, &newtio );
     fcntl(fd_232, F_SETFL, FNDELAY);

 

     // TCP 서버  ////////////////////////////////////////////////////////////////

     struct sockaddr_in addr_in;
     int option;

     fd_server = socket( PF_INET, SOCK_STREAM, 0 );
     if ( fd_server < 0 ) {
          perror( "tcp server open error:" );
          return 1;
     }

    

     option = 1;
     setsockopt( fd_server, SOL_SOCKET, SO_REUSEADDR, &option, sizeof( option ) );

     bzero( &addr_in, sizeof( struct sockaddr_in ) );
     addr_in.sin_family      = AF_INET;
     addr_in.sin_addr.s_addr = htonl( INADDR_ANY  );
     addr_in.sin_port        = htons( TCP_LISTEN_PORT);

     if( bind( fd_server, (struct sockaddr *)&addr_in, sizeof( struct sockaddr_in ) ) < 0 ) {
          perror( "tcp bind error :" );
          close( fd_server );
          return 1;
     }

 

     if ( 0 > listen( fd_server, 1 ) ) {
          perror("tcp listen error :");
          close( fd_server );
          return 1;
     }

 

     // poll 초기화 및 등록  ////////////////////////////////////////////////////

     poll_events[0].fd  = fd_server;    // 서버 소켙의 파일 디스크립터 저정
     poll_events[0].events = POLLIN | POLLERR;         // 수신된 자료가 있는지, 에러가 있는지
     poll_events[0].revents = 0;
     poll_events[1].fd  = 0;      // 아직 클라이언트와 연결되지 않았음
     poll_events[1].events = POLLIN | POLLERR;         // 수신된 자료가 있는지, 에러가 있는지
     poll_events[1].revents = 0;

 

     // 자료 송수신 ////////////////////////////////////////////////////////////
     while ( 1 ) {
          int     poll_state;
          int  ndx_poll;

  

          poll_state = poll(                                              // poll()을 호출하여 event 발생 여부 확인
                                     (struct pollfd*)&poll_events,   // event 등록 변수
                                     2,                                       // 체크할 pollfd 개수
                                     1000       // time out 시간
                                );

 

          if ( 0 < poll_state ) {                                         // 발생한 event 가 있음
              for ( ndx_poll= 0; ndx_poll < 2; ndx_poll++ ) {
                   if ( poll_events[ndx_poll].revents & POLLIN ) {  // event 가 자료 수신?

                       if ( 0 == ndx_poll ) {
                            on_accept();
                       } else {
                            on_data();
                       }
                   }
    

                   if ( poll_events[ndx_poll].revents & POLLERR ) {    // event 가 에러?
                       if ( 0 == ndx_poll ) {
                            printf( "서버 소켙 이상\n");
                       } else {
                            printf( "클라이언트 소켙 이상\n");
                       }
                       break;
                   }
              }
         }
     }
 

    close( fd_server);
    close( fd_232 );
    return 0;
}

 
 
 
===========

다음 강좌에서는 Ethernet의 UDP로 들어온 데이타를 RS232로 보내는 프로그램을 설명하도록 하겠습니다.