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


#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


int main( int argc, char *argv[])

{

    char can_port[BUFF_SIZE];

    char server_ip[BUFF_SIZE];


    if ( 3 > argc){

    printf( "인수가 모자릅니다. 포트의 서버 IP를 입력하여 주십시오.\n");

    printf( "실행방법: ]$ ./app_can_to_tcp can0 127.0.0.1\n");

    exit( 0);

}


    sprintf( can_port  , argv[1]);

    sprintf( server_ip , argv[2]);


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


int fd_sock;

struct sockaddr_can addr;

struct can_filter rfilter[4];

struct ifreq ifr;

int ifindex;


// can 포트를 open


if ( 0 > ( fd_sock = socket(PF_CAN, SOCK_RAW, CAN_RAW))) {

perror("socket");

return 1;

}


rfilter[0].can_id   = 0x32;

rfilter[0].can_mask = CAN_SFF_MASK;

rfilter[1].can_id   = 0x200;

rfilter[1].can_mask = 0x700;

rfilter[2].can_id   = 0x80123456;

rfilter[2].can_mask = 0x1FFFF000;

rfilter[3].can_id   = 0x80333333;

rfilter[3].can_mask = CAN_EFF_MASK;


setsockopt( fd_sock, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));


strcpy( ifr.ifr_name, can_port); // 사용할 CAN 번호

ioctl( fd_sock, SIOCGIFINDEX, &ifr);

ifindex = ifr.ifr_ifindex;


addr.can_family = AF_CAN;

addr.can_ifindex = ifindex;


if ( bind( fd_sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {

perror("bind");

return 1;

}


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


struct pollfd     poll_events;      // 체크할 event 정보를 갖는 struct

int    poll_state;


poll_events.fd        = fd_sock;

poll_events.events    = POLLIN | POLLERR;          // 수신된 자료가 있는지, 에러가 있는지

poll_events.revents   = 0;


// 자료 송수신 ////////////////////////////////////////////////////////////


while ( 1)

{

poll_state = poll( // poll()을 호출하여 event 발생 여부 확인

                           (struct pollfd*)&poll_events, // event 등록 변수

                           1, // 체크할 pollfd 개수

                           1000 // time out 시간

                         );


if ( 0 < poll_state) // 발생한 event 가 있음

{

if ( poll_events.revents & POLLIN) // event 가 자료 수신?

{

struct can_frame frame;

int rd_size;


rd_size = read( fd_sock, &frame, sizeof(struct can_frame));

if ( 0 > rd_size)

{

fprintf(stderr, "read error");

}

else if ( rd_size < sizeof( struct can_frame))

{

fprintf(stderr, "read: incomplete CAN frame\n");

return 1;

}

else {

int client_socket;

struct sockaddr_in  server_addr;

char   tx_buff[BUFF_SIZE+1];

int     ndx;


if (frame.can_id & CAN_EFF_FLAG)

printf("%8X  ", frame.can_id & CAN_EFF_MASK);

else

printf("%3X  ", frame.can_id & CAN_SFF_MASK);

if (frame.can_id & CAN_RTR_FLAG)

printf("remote request");


printf("  [%d] ", frame.can_dlc);


for ( ndx = 0; ndx < frame.can_dlc; ndx++) {

printf("%02X ", frame.data[ndx]);

tx_buff[ndx] = frame.data[ndx];

}

printf("\n");

tx_buff[ndx++] = '\0';


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( server_ip);


if( -1 == connect( client_socket, (struct sockaddr*)&server_addr, sizeof( server_addr) ) )

{

printf( "접속 실패\n");

}

else

{

write( client_socket, tx_buff, ndx );

close( client_socket );

}

}

}

if ( poll_events.revents & POLLERR)       // event 가 에러?

{

printf( "통신 라인에 에러가 발생, 프로그램 종료");

break;

}

}

}


close( fd_sock );

return 0;

}




===========

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