Linux-UDP-Socket编程
接收CAN总线上的数据并将其发送出去
创建客户端:
/******************************************************************** * copyright (C) 2018 all rights reserved * @file: server.c * @Created: 2018-4-16 13:22nd * @Author: Yinrui Zhu * @Description: test user eth0 * @Modify Date: 2018-4-13 *********************************************************************/ #include <limits.h> #include <stdint.h> #include <getopt.h> #include <libgen.h> #include <signal.h> #include <net/if.h> #include <sys/ioctl.h> #include <linux/can.h> #include <linux/can/raw.h> #include <sys/types.h> #include <sys/socket.h> #include <pthread.h> #include <arpa/inet.h> #include <errno.h> #include <netinet/in.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #define SERVER_PORT 8000 #define BUFFER_SIZE 1024 #define ipaddr "192.168.200.110" #define FILE_NAME_MAX_SIZE 512 int main() { int nbytes,i,addrlen; char abuf[12]; char bbuf[12]; char cbuf[12]; char dbuf[12]; char ebuf[12]; int s; struct sockaddr_can addr; struct ifreq ifr; struct can_frame frame; struct can_filter rfilter[5]; int family = PF_CAN, type = SOCK_RAW, proto = CAN_RAW; system("ip link set can0 type can bitrate 125000 triple-sampling on"); sleep(2); system("ip link set can0 up"); s = socket(family, type, proto); //创建套接字 strcpy(ifr.ifr_name, "can0"); ioctl(s, SIOCGIFINDEX,&ifr); //指定can0设备 addr.can_family = family; //addr.can_family = AF_CAN; addr.can_ifindex = ifr.ifr_ifindex; bind( s, (struct sockaddr *)&addr, sizeof(addr) ); //将套接字与can0设备绑定 /*定义接收规则*/ rfilter[0].can_id = 0x10; //接收ID为0x10的报文 rfilter[0].can_mask = CAN_SFF_MASK; rfilter[1].can_id = 0x20; //接收ID为0x20的报文 rfilter[1].can_mask = CAN_SFF_MASK; rfilter[2].can_id = 0x40; //接收ID为0x40的报文 rfilter[2].can_mask = CAN_SFF_MASK; rfilter[3].can_id = 0x80; //接收ID为0x80的报文 rfilter[3].can_mask = CAN_SFF_MASK; rfilter[4].can_id = 0x800; //接收ID为0x800的报文 rfilter[4].can_mask = CAN_EFF_MASK; if( setsockopt( s,SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter) ) != 0 ) //设置过滤规则 { perror("setsockopt"); exit(1); } /*服务端地址*/ struct sockaddr_in server_addr; bzero( &server_addr, sizeof(server_addr) ); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = inet_addr(ipaddr); server_addr.sin_port = htons(SERVER_PORT); addrlen = sizeof(server_addr); /*创建socket*/ int client_socket_fd = socket(AF_INET, SOCK_DGRAM, 0); if( client_socket_fd == -1 ) { perror("Creat Socket Failed!"); exit(1); } /*数据传输*/ while(1) { /*can接收数据*/ if( nbytes = read(s, &frame, sizeof(frame)) < 0 ) { perror("read"); return 1; } switch(frame.can_id) { case 0x10: abuf[0] = ((frame.can_id>>24)&0xFF); abuf[1] = ((frame.can_id>>16)&0xFF); abuf[2] = ((frame.can_id>>8)&0xFF); abuf[3] = (frame.can_id&0xFF); for( i=4; i<frame.can_dlc+4; i++) { abuf[i] = frame.data[i-4]; printf("ID=0x%x DLC=%d abuf[%d]=0x%x\n", frame.can_id, frame.can_dlc, i, abuf[i]); } break; case 0x20: bbuf[0] = ((frame.can_id>>24)&0xFF); bbuf[1] = ((frame.can_id>>16)&0xFF); bbuf[2] = ((frame.can_id>>8)&0xFF); bbuf[3] = (frame.can_id&0xFF); for( i=4; i<frame.can_dlc+4; i++) { bbuf[i] = frame.data[i-4]; printf("ID=0x%x DLC=%d bbuf[%d]=0x%x\n", frame.can_id, frame.can_dlc, i, bbuf[i]); } break; case 0x40: cbuf[0] = ((frame.can_id>>24)&0xFF); cbuf[1] = ((frame.can_id>>16)&0xFF); cbuf[2] = ((frame.can_id>>8)&0xFF); cbuf[3] = (frame.can_id&0xFF); for( i=4; i<frame.can_dlc+4; i++) { cbuf[i] = frame.data[i-4]; printf("ID=0x%x DLC=%d cbuf[%d]=0x%x\n", frame.can_id, frame.can_dlc, i, cbuf[i]); } break; case 0x80: dbuf[0] = ((frame.can_id>>24)&0xFF); dbuf[1] = ((frame.can_id>>16)&0xFF); dbuf[2] = ((frame.can_id>>8)&0xFF); dbuf[3] = (frame.can_id&0xFF); for( i=4; i<frame.can_dlc+4; i++) { dbuf[i] = frame.data[i-4]; printf("ID=0x%x DLC=%d dbuf[%d]=0x%x\n", frame.can_id, frame.can_dlc, i, dbuf[i]); } break; case 0x80000800: ebuf[0] = ((frame.can_id>>24)&0xFF); ebuf[1] = ((frame.can_id>>16)&0xFF); ebuf[2] = ((frame.can_id>>8)&0xFF); ebuf[3] = (frame.can_id&0xFF); for( i=4; i<frame.can_dlc+4; i++) { ebuf[i] = frame.data[i-4]; printf("ID=0x%x DLC=%d ebuf[%d]=0x%x\n", frame.can_id, frame.can_dlc, i, ebuf[i]); } break; default : printf("The recive can indetifer ID is wrong!\n"); break; } sendto(client_socket_fd,abuf,12,0,(struct sockaddr*)&server_addr, addrlen); sendto(client_socket_fd,bbuf,12,0,(struct sockaddr*)&server_addr, addrlen); sendto(client_socket_fd,cbuf,12,0,(struct sockaddr*)&server_addr, addrlen); sendto(client_socket_fd,dbuf,12,0,(struct sockaddr*)&server_addr, addrlen); sendto(client_socket_fd,ebuf,12,0,(struct sockaddr*)&server_addr, addrlen); printf("Hello.\n"); /*接收数据*/ /* size_t recv_len = 0; char buffer[BUFFER_SIZE]; bzero(buffer, BUFFER_SIZE); recv_len = recvfrom(server_socket_fd, buffer, BUFFER_SIZE, 0 ,(struct sockaddr*)&client_addr, &client_addr_length); if( recv_len == -1 ) { perror("Receive Data Failed:"); exit(1); } */ /*从buffer中拷贝出file_name*/ /* char file_name[FILE_NAME_MAX_SIZE +1]; bzero(file_name,FILE_NAME_MAX_SIZE+1); strncpy(file_name, buffer, strlen(buffer)>FILE_NAME_MAX_SIZE ? FILE_NAME_MAX_SIZE:strlen(buffer)); printf("%s\n",file_name); printf("%s\n",buffer); */ } system("ip link set can0 down"); close(client_socket_fd); return 0; }
编译生成client_can 使用说明:
1、运行可执行文件client_can(./client_can) 2、利用网络调试工具Socket_Tool.exe(F:\嵌入式资料\AM335X\BeagleBone\UDP_test\Socket_Tool.exe) 创建服务其端口: a、192.168.200.110(8000) 3、另一快开发板can0设置: a、ip link set can0 down b ip link set can0 type can bitrate 125000 triple-sampling on c ip link set can0 up d cansend can0 -i 0x80 0xaa 0x11 0x55 0x44 0x11 0x22 0x33 0x66 4、当can0的CANL、CANH上面有数据时:运行。/client_can的开发板就可以接收的相应的数据( ID=0x80 DLC=8 dbuf[4]=0x55 ID=0x80 DLC=8 dbuf[5]=0x55 ID=0x80 DLC=8 dbuf[6]=0x55 ID=0x80 DLC=8 dbuf[7]=0x55 ID=0x80 DLC=8 dbuf[8]=0xaa ID=0x80 DLC=8 dbuf[9]=0xaa ID=0x80 DLC=8 dbuf[10]=0xaa ID=0x80 DLC=8 dbuf[11]=0xac Hello. ),同时将数据通过网络发送给PC机的server服务器端 ( 14:59:16 收到数据:{00 00 00 10 55 55 55 55 AA AA AA AC } 14:59:16 收到数据:{14 69 69 0D 00 79 FE B6 02 00 00 00 }ii 14:59:16 收到数据:{24 08 00 00 00 00 00 00 08 FD F7 BE }$ 14:59:16 收到数据:{00 00 00 80 55 55 55 55 AA AA AA AC } 14:59:16 收到数据:{B8 7B FC B6 00 00 00 00 4D 8C 00 00 }竰 )。
PC端的服务器端口配置:
服务器端口:
/******************************************************************** * copyright (C) 2018 all rights reserved * @file: server.c * @Created: 2018-4-16 13:22nd * @Author: Yinrui Zhu * @Description: test user eth0 * @Modify Date: 2018-4-13 *********************************************************************/ #include <limits.h> #include <stdint.h> #include <getopt.h> #include <libgen.h> #include <signal.h> #include <net/if.h> #include <sys/ioctl.h> #include <linux/can.h> #include <linux/can/raw.h> #include <sys/types.h> #include <sys/socket.h> #include <pthread.h> #include <arpa/inet.h> #include <errno.h> #include <netinet/in.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #define SERVER_PORT 8000 #define BUFFER_SIZE 1024 #define ipaddr "192.168.200.110" #define FILE_NAME_MAX_SIZE 512 int main() { int nbytes,i,addrlen; char abuf[12]; char bbuf[12]; char cbuf[12]; char dbuf[12]; char ebuf[12]; int s; struct sockaddr_can addr; struct ifreq ifr; struct can_frame frame; struct can_filter rfilter[5]; int family = PF_CAN, type = SOCK_RAW, proto = CAN_RAW; system("ip link set can0 type can bitrate 125000 triple-sampling on"); sleep(2); system("ip link set can0 up"); s = socket(family, type, proto); //创建套接字 strcpy(ifr.ifr_name, "can0"); ioctl(s, SIOCGIFINDEX,&ifr); //指定can0设备 addr.can_family = family; //addr.can_family = AF_CAN; addr.can_ifindex = ifr.ifr_ifindex; bind( s, (struct sockaddr *)&addr, sizeof(addr) ); //将套接字与can0设备绑定 /*定义接收规则*/ rfilter[0].can_id = 0x10; //接收ID为0x10的报文 rfilter[0].can_mask = CAN_SFF_MASK; rfilter[1].can_id = 0x20; //接收ID为0x20的报文 rfilter[1].can_mask = CAN_SFF_MASK; rfilter[2].can_id = 0x40; //接收ID为0x40的报文 rfilter[2].can_mask = CAN_SFF_MASK; rfilter[3].can_id = 0x80; //接收ID为0x80的报文 rfilter[3].can_mask = CAN_SFF_MASK; rfilter[4].can_id = 0x800; //接收ID为0x800的报文 rfilter[4].can_mask = CAN_EFF_MASK; if( setsockopt( s,SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter) ) != 0 ) //设置过滤规则 { perror("setsockopt"); exit(1); } /*创建UDP套接口*/ struct sockaddr_in server_addr; bzero( &server_addr, sizeof(server_addr) ); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(SERVER_PORT); /*创建socket*/ int server_socket_fd = socket(AF_INET, SOCK_DGRAM, 0); if( server_socket_fd == -1 ) { perror("Creat Socket Failed!"); exit(1); } /*绑定套接口*/ if(-1 == ( bind( server_socket_fd, (struct sockaddr*)&server_addr, sizeof(server_addr) ) ) ) { perror("Server Bind Failed: "); exit(1); } /*数据传输*/ while(1) { /*can接收数据*/ if( nbytes = read(s, &frame, sizeof(frame)) < 0 ) { perror("read"); return 1; } switch(frame.can_id) { case 0x10: abuf[0] = ((frame.can_id>>24)&0xFF); abuf[1] = ((frame.can_id>>16)&0xFF); abuf[2] = ((frame.can_id>>8)&0xFF); abuf[3] = (frame.can_id&0xFF); for( i=4; i<frame.can_dlc+4; i++) { abuf[i] = frame.data[i-4]; printf("ID=0x%x DLC=%d abuf[%d]=0x%x\n", frame.can_id, frame.can_dlc, i, abuf[i]); } break; case 0x20: bbuf[0] = ((frame.can_id>>24)&0xFF); bbuf[1] = ((frame.can_id>>16)&0xFF); bbuf[2] = ((frame.can_id>>8)&0xFF); bbuf[3] = (frame.can_id&0xFF); for( i=4; i<frame.can_dlc+4; i++) { bbuf[i] = frame.data[i-4]; printf("ID=0x%x DLC=%d bbuf[%d]=0x%x\n", frame.can_id, frame.can_dlc, i, bbuf[i]); } break; case 0x40: cbuf[0] = ((frame.can_id>>24)&0xFF); cbuf[1] = ((frame.can_id>>16)&0xFF); cbuf[2] = ((frame.can_id>>8)&0xFF); cbuf[3] = (frame.can_id&0xFF); for( i=4; i<frame.can_dlc+4; i++) { cbuf[i] = frame.data[i-4]; printf("ID=0x%x DLC=%d cbuf[%d]=0x%x\n", frame.can_id, frame.can_dlc, i, cbuf[i]); } break; case 0x80: dbuf[0] = ((frame.can_id>>24)&0xFF); dbuf[1] = ((frame.can_id>>16)&0xFF); dbuf[2] = ((frame.can_id>>8)&0xFF); dbuf[3] = (frame.can_id&0xFF); for( i=4; i<frame.can_dlc+4; i++) { dbuf[i] = frame.data[i-4]; printf("ID=0x%x DLC=%d dbuf[%d]=0x%x\n", frame.can_id, frame.can_dlc, i, dbuf[i]); } break; case 0x80000800: ebuf[0] = ((frame.can_id>>24)&0xFF); ebuf[1] = ((frame.can_id>>16)&0xFF); ebuf[2] = ((frame.can_id>>8)&0xFF); ebuf[3] = (frame.can_id&0xFF); for( i=4; i<frame.can_dlc+4; i++) { ebuf[i] = frame.data[i-4]; printf("ID=0x%x DLC=%d ebuf[%d]=0x%x\n", frame.can_id, frame.can_dlc, i, ebuf[i]); } break; default : printf("The recive can indetifer ID is wrong!\n"); break; } /*定义一个地址,用于蒱获客户端地址*/ struct sockaddr_in client_addr; socklen_t client_addr_length = sizeof(client_addr); /*接收数据*/ size_t recv_len = 0; char buffer[BUFFER_SIZE]; bzero(buffer, BUFFER_SIZE); recv_len = recvfrom(server_socket_fd, buffer, BUFFER_SIZE, 0 ,(struct sockaddr*)&client_addr, &client_addr_length); if( recv_len == -1 ) { perror("Receive Data Failed:"); exit(1); } /*从buffer中拷贝出file_name*/ char file_name[FILE_NAME_MAX_SIZE +1]; bzero(file_name,FILE_NAME_MAX_SIZE+1); strncpy(file_name, buffer, strlen(buffer)>FILE_NAME_MAX_SIZE ? FILE_NAME_MAX_SIZE:strlen(buffer)); printf("%s\n",file_name); printf("%s\n",buffer); sendto(server_socket_fd,buffer,recv_len,0,(struct sockaddr*)&client_addr, client_addr_length); sendto(server_socket_fd,abuf,12,0,(struct sockaddr*)&client_addr, client_addr_length); sendto(server_socket_fd,bbuf,12,0,(struct sockaddr*)&client_addr, client_addr_length); sendto(server_socket_fd,cbuf,12,0,(struct sockaddr*)&client_addr, client_addr_length); sendto(server_socket_fd,dbuf,12,0,(struct sockaddr*)&client_addr, client_addr_length); sendto(server_socket_fd,ebuf,12,0,(struct sockaddr*)&client_addr, client_addr_length); printf("Hello.\n"); } system("ip link set can0 down"); close(server_socket_fd); return 0; }
PC端客户端配置:
编译生成server.can 使用说明:
1、运行可执行文件server_can(./server_can) 2、利用网络调试工具Socket_Tool.exe(F:\嵌入式资料\AM335X\BeagleBone\UDP_test\Socket_Tool.exe) 创建客户端口: a、192.168.200.70(8000) 3、另一快开发板can0设置: a、ip link set can0 down b ip link set can0 type can bitrate 125000 triple-sampling on c ip link set can0 up d cansend can0 -i 0x80 0xaa 0x11 0x55 0x44 0x11 0x22 0x33 0x66 4、当can0的CANL、CANH上面有数据时:运行。/server_can的开发板就可以接收的相应的数据( ID=0x80 DLC=8 dbuf[4]=0x55 ID=0x80 DLC=8 dbuf[5]=0x55 ID=0x80 DLC=8 dbuf[6]=0x55 ID=0x80 DLC=8 dbuf[7]=0x55 ID=0x80 DLC=8 dbuf[8]=0xaa ID=0x80 DLC=8 dbuf[9]=0xaa ID=0x80 DLC=8 dbuf[10]=0xaa ID=0x80 DLC=8 dbuf[11]=0xac Hello. ),但是接收到的数据只能发送一次。因为该板子作为服务器端口,需要客户端给该板子发送一个信号(any)。最为客户端的PC机才能接收服务器端(开发板)发过来的数据 ( 5:13:26 收到数据:{24 08 00 00 00 00 00 00 08 DD D4 BE }$ 15:13:26 收到数据:{28 01 00 00 99 87 00 00 C5 8F 00 00 }( 15:13:26 收到数据:{B8 3B F1 B6 00 00 00 00 91 8F 00 00 }?穸 15:13:28 发送数据:猍1次] 15:13:28 收到数据:{AA } 15:13:28 收到数据:{00 00 00 10 55 55 55 55 AA AA AA AC } 15:13:28 收到数据:{14 69 69 0D 00 39 F3 B6 02 00 00 00 }ii 15:13:28 收到数据:{24 08 00 00 00 00 00 00 08 DD D4 BE }$ 15:13:28 收到数据:{28 01 00 00 99 87 00 00 C5 8F 00 00 }( 15:13:28 收到数据:{B8 3B F1 B6 00 00 00 00 91 8F 00 00 }?穸 )。