socket can发包后,接收阻塞
huzid 2019-01-23 03:28:53 需要用socket can通信,主线程中:创建socket、建立接收线程、发送数据包。
现在遇到的问题:在发送数据包之前,接收线程可以正常接收数据包;但主线程发送数据包后,子线程就在select地方阻塞。
请问是什么问题?
代码如下:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <linux/socket.h>
#include <linux/can.h>
#include <linux/can/error.h>
#include <linux/can/raw.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
#define uint8_t unsigned char
#define int8_t signed char
#define uint16_t unsigned short int
#define int16_t signed short int
#define uint32_t unsigned int
#define int32_t signed int
#define uint64_t unsigned long long int
#define int64_t signed long long int
#define DWORD unsigned int
#define UINT unsigned int
#define USHORT unsigned short int
#define CHAR signed char
#define UCHAR unsigned char
#define BYTE unsigned char
#define ULONG unsigned int
#define INT signed int
#define PVOID void*
#define LPVOID void*
#define HANDLE void*
#define BOOL BYTE
#define msleep(ms) usleep((ms)*1000)
#define min(a,b) (((a) < (b)) ? (a) : (b))
#ifndef AF_CAN
#define AF_CAN 29
#endif
#ifndef PF_CAN
#define PF_CAN AF_CAN
#endif
#define errout(_s) fprintf(stderr, "error class: %s\n", (_s))
#define errcode(_d) fprintf(stderr, "error code: %02x\n", (_d))
static void handle_err_frame(const struct can_frame *fr)
{
if (fr->can_id & CAN_ERR_TX_TIMEOUT) {
errout("CAN_ERR_TX_TIMEOUT");
}
if (fr->can_id & CAN_ERR_LOSTARB) {
errout("CAN_ERR_LOSTARB");
errcode(fr->data[0]);
}
if (fr->can_id & CAN_ERR_CRTL) {
errout("CAN_ERR_CRTL");
errcode(fr->data[1]);
}
if (fr->can_id & CAN_ERR_PROT) {
errout("CAN_ERR_PROT");
errcode(fr->data[2]);
errcode(fr->data[3]);
}
if (fr->can_id & CAN_ERR_TRX) {
errout("CAN_ERR_TRX");
errcode(fr->data[4]);
}
if (fr->can_id & CAN_ERR_ACK) {
errout("CAN_ERR_ACK");
}
if (fr->can_id & CAN_ERR_BUSOFF) {
errout("CAN_ERR_BUSOFF");
}
if (fr->can_id & CAN_ERR_BUSERROR) {
errout("CAN_ERR_BUSERROR");
}
if (fr->can_id & CAN_ERR_RESTARTED) {
errout("CAN_ERR_RESTARTED");
}
}
#define myerr(str) fprintf(stderr, "%s, %s, %d: %s\n", __FILE__, __func__, __LINE__, str)
static void print_frame(struct can_frame *fr)
{
int i;
printf("%08x\n", fr->can_id);
printf("%08x\n", CAN_EFF_MASK);
//if(fr->data[0] != 0x01)
// return;
printf("%08x\n", fr->can_id & CAN_EFF_MASK);
//printf("%08x\n", fr->can_id);
printf("dlc = %d\n", fr->can_dlc);
printf("data = ");
for (i = 0; i < fr->can_dlc; i++)
printf("%02x ", fr->data[i]);
printf("\n");
}
static void generate_frame(struct can_frame *fr)
{
printf("generate_frame.");
//printf("mask:%08x.\n",CAN_EFF_MASK);
fr->can_id = 0x00000555;// | CAN_EFF_MASK;
fr->can_dlc = 8;
fr->data[0] = 0x01;
fr->data[1] = 0x01;
fr->data[2] = 0x00;
fr->data[3] = 0x00;
fr->data[4] = 0x00;
fr->data[5] = 0x04;
fr->data[6] = 0x05;
fr->data[7] = 0x00;
}
void * rx_thread(void *data)
{
int ret = 0;
struct can_frame frdup;
struct timeval tv;
fd_set rset;
FD_ZERO(&rset);
printf("RX thread.-------------------");
int s = *(int *)data;
FD_SET(s, &rset);
while (1)
{
/*parse can data.*/
tv.tv_sec = 1;
tv.tv_usec = 0;
ret = select(s+1, &rset, NULL, NULL, NULL);
if (ret == 0) {
myerr("select time out");
//return -1;
}
ret = read(s, &frdup, sizeof(frdup));
if (ret < sizeof(frdup)) {
myerr("read failed");
//return -1;
continue;
}
printf("recv can frame, can_id:%d.-------\n", frdup.can_id);
if (frdup.can_id & CAN_ERR_FLAG) { /* 鍑洪敊璁惧閿欒 */
handle_err_frame(&frdup);
myerr("CAN device error");
continue;
}
print_frame(&frdup);
}
myerr("level RX thread.-------------");
close(s);
pthread_exit(0);
}
static int test_can_rw(int fd, int master)
{
int ret, i;
struct can_frame fr, frdup;
struct timeval tv;
fd_set rset;
pthread_t rx_thread_id;
pthread_create(&rx_thread_id, NULL, rx_thread, &fd);
generate_frame(&frdup);
//print_frame(&frdup);
int send = 0;
while (1) {
sleep(1);
#if 1
if (send < 5 ) {
ret = write(fd, &frdup, sizeof(frdup));
if (ret < 0) {
myerr("write failed============");
return -1;
}
send++;
printf("frame len:%d.\n", ret);
myerr("write ok.=====================");
}
#endif
}
return 0;
}
int main(int argc, char* argv[])
{
int s;
int ret;
struct sockaddr_can addr;
struct ifreq ifr;
int master;
srand(time(NULL));
s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (s < 0) {
perror("socket PF_CAN failed");
return 1;
}
strcpy(ifr.ifr_name, "can0");
ret = ioctl(s, SIOCGIFINDEX, &ifr);
if (ret < 0) {
perror("ioctl failed");
return 1;
}
addr.can_family = PF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
ret = bind(s, (struct sockaddr *)&addr, sizeof(addr));
if (ret < 0) {
perror("bind failed");
return 1;
}
if (0) {
struct can_filter filter[2];
filter[0].can_id = 0x200 | CAN_EFF_FLAG;
filter[0].can_mask = 0xFFF;
filter[1].can_id = 0x20F | CAN_EFF_FLAG;
filter[1].can_mask = 0xFFF;
ret = setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, &filter, sizeof(filter));
if (ret < 0) {
perror("setsockopt failed");
return 1;
}
}
test_can_rw(s, master);
close(s);
return 0;
}