C221-S3C6410 보드에 있는 TCP로 들어오는 데이터를 CAN 통신으로 보내는 프로그램은 다음과 같습니다.

 

#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 <linux/can.h>
#include <linux/can/raw.h>

#define BUFF_SIZE  1024
#define TCP_LISTEN_PORT 4000

int  fd_can;                                                 // can 통신을 위한 파일 디스크립터
int  fd_server;                                             // TCP 서버 소켙의 파일 디스크립터
int  fd_client;
struct  sockaddr_can  addr_can;
struct  pollfd       poll_events[2];                   // TCP 서버 소켙과 클라이언트 소켙을 위해 2개 사용

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

 

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

             if ( 8 < rd_cnt)                        // CAN 통신에서는 최고 8 바이트 전송
             rd_cnt = 8;

             printf( "receive:");                    // 수령 메시지 화면 출력
             frame.can_id  = 0x32;
             frame.can_dlc = 8;
             memset( frame.data, 0, 8);
             for ( ndx_loop = 0; ndx_loop < rd_cnt; ndx_loop++)
             {
                    printf( "%2x ", buff_rcv[ndx_loop]);
                    frame.data[ndx_loop] = buff_rcv[ndx_loop];
             }
             printf( "\n");

             sendto( fd_can, &frame, sizeof(struct can_frame), 0, (struct sockaddr*)&addr_can, sizeof(addr_can));
      }
}

 

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[])
{
       char can_port[1024];

   

       if ( 2 > argc) {
             printf( "인수가 모자릅니다. 시리얼 포트를 입력하여 주시오.\n");
             printf( "실행방법: ]$ ./app_tcp_to_can can0\n");
             exit( 0);
       }

       sprintf( can_port, "%s", argv[1]);

 

       // can 포트 open ////////////////////////////////////////////////////////////

       struct ifreq   ifr;
       int     ifindex;

      

       if ( 0 > ( fd_can = socket(PF_CAN, SOCK_RAW, CAN_RAW)) ) {
              perror("socket");
              return 1;
       }

      

       strcpy(ifr.ifr_name, can_port);
       ioctl( fd_can, SIOCGIFINDEX, &ifr);
       ifindex = ifr.ifr_ifindex;

       addr_can.can_family  = AF_CAN;
       addr_can.can_ifindex = ifindex; /* send via this interface */

       if ( 0 > bind( fd_can, (struct sockaddr *)&addr_can, sizeof(addr_can)) ) {
             perror("bind");
             return 1;
       }

 

       // 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_can );

     return 0;
}

 

 

 

===========

다음 강좌에서는 udp to can 프로그램을 설명하도록 하겠습니다