飞凌嵌入式
直播中

donatello1996

9年用户 737经验值
擅长:MEMS/传感技术
私信 关注
[技术]

【飞凌嵌入式OKMX8MP-C 开发板试用体验】SCTP通信

      SCTP通信是区别于TCP通信和UDP通信外的一种传输层协议通信,兼具了TCP和UDP的部分优点,比如SCTP不是以字节为单位传输,而是以数据块为单位传输;SCTP传输的消息是可靠的,不像UDP那样是不可靠的;SCTP传输可以使用多路径,不像TCP那样一个socket只能传输一个路径的信息等;除此之外,SCTP通信相比TCP和UDP通信更多了一层安全保障,那就是四步握手。要使ARM64架构的板子支持SCTP通信,是需要打开内核选项的,不像x86那样默认支持SCTP:

41.JPG

重新编译内核文件Image并替换,板子就支持SCTP通信了,但是在实际通信过程中发现了诸多问题,至今尚未解决,目前只完成了建立socket bind() listen()等步骤,还未能正常进行通信,后续有更新进度的话我会编辑此帖子进行更新。

安装SCTP第三方软件库有两个方法,一是通过apt安装:
  1. apt install lksctp-tools

或是直接从支持网站中下载源码包进行编译,下载lksctp-tools-1.0.18并解压:
43.JPG

  1. ./bootstrap
  2. ./configure
  3. make install实际测试这两种方式区别不大,因此就按照apt安装的方式进行,首先编写server端代码,依次进行socket() bind() listen()等操作:
  1.     if((sockfd = socket(AF_INET,SOCK_SEQPACKET,IPPROTO_SCTP)) == -1)
  2.     {
  3.         printf(" create socket error: %s (errno :%d)n",strerror(errno),errno);
  4.         return 0;
  5.     }  
  6.     printf("========= sockfd = %d=========n" , sockfd);

  7.     bzero(&servaddr,sizeof(servaddr));
  8.     servaddr.sin_family = AF_INET;
  9.     servaddr.sin_port = htons(SERVER_PORT);
  10.     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  11.     inet_pton(AF_INET , SERVER_IP , &servaddr.sin_addr);   

  12.     int ret;
  13.     ret = bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
  14.     printf("========= bind = %d=========n" , ret);

  15.     struct sctp_event_subscribe events;
  16.     bzero(&events,sizeof(events));
  17.     events.sctp_data_io_event = 1;
  18.     ret = setsockopt(sockfd,IPPROTO_SCTP,SCTP_EVENTS,&events,sizeof(events));
  19.     printf("========= setsockopt = %d=========n" , ret);

  20.     ret = listen(sockfd,LISTENQ);
  21.     printf("========= listen = %d=========n" , ret);

创建发送线程:
  1.    pthread_create(&id1 , NULL , Thread_Sctp_Send , NULL);

  2. void *Thread_Sctp_Send(void * args)
  3. {
  4.     struct sctp_sndrcvinfo sri;
  5.     while(1)
  6.     {
  7.         char msg[MAXLINE] = "Interesting7777777";
  8.         sctp_sendmsg(sockfd,msg,sizeof(msg),(struct sockaddr *)&cliaddr,800,sri.sinfo_ppid,(sri.sinfo_flags),sri.sinfo_stream,0,0);
  9.         sleep(1);
  10.     }
  11. }

主循环中进行循环接收:
  1.     while(1)
  2.     {
  3.         socklen_t len=sizeof(struct sockaddr_in);
  4.         size_t rd_sz=sctp_recvmsg(sockfd,rdbuf,sizeof(rdbuf),(struct sockaddr *)&cliaddr,&len,&sri,&flag);
  5.         printf("=========server rdbuf = %s =========n" , rdbuf);
  6.     }

然后是client端的代码,与server端大同小异:
  1.    int flag = 0;
  2.     if((sockfd = socket(AF_INET,SOCK_SEQPACKET,IPPROTO_SCTP)) == -1)
  3.     {
  4.         printf(" create socket error: %s (errno :%d)n",strerror(errno),errno);
  5.         return 0;
  6.     }  
  7.     printf("========= sockfd = %d =========n" , sockfd);
  8.    
  9.     struct sockaddr_in servaddr;
  10.     bzero(&servaddr,sizeof(servaddr));
  11.     servaddr.sin_family=AF_INET;
  12.     servaddr.sin_port=htons(SERVER_PORT);
  13.     inet_pton(AF_INET , SERVER_IP , &servaddr.sin_addr);

  14.     struct sctp_event_subscribe events;
  15.     bzero(&events,sizeof(events));
  16.     events.sctp_data_io_event=1;
  17.     int ret = setsockopt(sockfd,IPPROTO_SCTP,SCTP_EVENTS,&events,sizeof(events));
  18.     printf("========= setsockopt = %d=========n" , ret);

  19.     ret = connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr));
  20.     printf("========= connect = %d=========n" , ret);

  21.     // if(flag == 0)
  22.     //     sctp_cli(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
  23.     // else
  24.     //     sctp_cli_all(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));

  25.     if(ret >= 0)
  26.         pthread_create(&id1 , NULL , Thread_Sctp_Recv , NULL);

  27.     char rdbuf[MAXLINE] = "Interesting666666";
  28.     int len = SCTP_MAXLINE , rd_sz=strlen(rdbuf);
  29.     struct sctp_sndrcvinfo sri;

主循环发送:

  1.     while(1)
  2.     {
  3.         sctp_sendmsg(sockfd,rdbuf,rd_sz,(struct sockaddr *)&servaddr,len,sri.sinfo_ppid,(sri.sinfo_flags),sri.sinfo_stream,0,0);
  4.         sleep(1);
  5.     }

接收线程:

  1. void *Thread_Sctp_Recv(void * args)
  2. {
  3.     char rdbuf[MAXLINE];
  4.     struct sctp_sndrcvinfo sri;
  5.     int flag;
  6.     while(1)
  7.     {
  8.         socklen_t len = sizeof(struct sockaddr_in);
  9.         size_t rd_sz=sctp_recvmsg(sockfd,rdbuf,sizeof(rdbuf),(struct sockaddr *)&cliaddr,&len,&sri,&flag);
  10.         printf("=========client rdbuf = %s =========n" , rdbuf);
  11.     }
  12. }
实际运行中,server端的socket() bind() listen()返回值均正常,但是接收循环中陷入了无数据但一直打印接收的死循环中,这是很严重的问题,需要后续跟进:
42.JPG

更多回帖

发帖
×
20
完善资料,
赚取积分