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;
}


...全文
3497 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
Nullber 2020-11-04
  • 打赏
  • 举报
回复
没设置超时??? https://baike.baidu.com/item/select/12504672?fr=aladdin 参数一:最大的文件描述符加1。 参数二:用于检查可读性, 参数三:用于检查可写性, 参数四:用于检查带外数据, 参数五:一个指向timeval结构的指针,用于决定select等待I/o的最长时间。如果为空将一直等待。timeval结构的定义:struct timeval{ long tv_sec; // seconds long tv_usec; // microseconds }
lingdulebaishi 2020-11-03
  • 打赏
  • 举报
回复
ret = select(s+1, &rset, NULL, NULL, NULL);最后一个NULL所以阻塞,为什么tv.tv_sec = 1; tv.tv_usec = 0;没有用到有没有想过

23,120

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧