EtherCAT数据帧发送socket通信笔记

目录

初始化网卡

创建一个套接字 socket():

setsockopt:

ioctl

绑定端口

send()函数

recv()函数


/* initialise SOEM, bind socket to ifname */
if (ec_init(ifname))
//功能:初始化SOEM,将socket绑定到ifname

 初始化网卡

 /* we use RAW packet socket, with packet type ETH_P_ECAT */
//原函数:int socket(int domain, int type,int protocol);

 int *psock;
 *psock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ECAT));
#define ETH_P_ECAT 0x88A4
#define SOCK_RAW 3

创建一个套接字 socket():

出错返回-1,成功返回文件描述符

domain是网络程序所在的主机采用的通讯协族(AF_UNIX和AF_INET等)。

type是网络程序所采用的通讯协议(SOCK_STREAM,SOCK_DGRAM等)。在使用SOCK_RAW或SOCK_DGRAM和SOCK_PACKET时,在sendto和recvfrom中使用的地址类型不同,前两者使用sockaddr_ll类型的地址,而后者使用sockaddr类型的地址。【此处用原始套接字(SOCK_RAW):(对应多个协议,传输穿透传输层)ICMP;允许程序使用底层协议,原始套接字允许对底层协议如IP或ICMP进行直接访问,功能强大但使用较为不便,主要用于一些协议的开发】

protocol选择协议

        

r = setsockopt(*psock, SOL_SOCKET, SO_DONTROUTE, &i, sizeof(i));
//SO_DONTROUTE	不查找路由	int
/*SO_DONTROUTE
指定传出消息是否绕过标准路由工具。目标必须在直接连接的网络上,
并且根据目标地址将消息定向到适当的网络接口。
此选项的效果(如果有)取决于所使用的协议。
此选项在optval参数中采用int值 。这是BOOL选项。*/

setsockopt:

        是Linux系统中的一个系统调用,用于设置套接字选项。通过setsockopt函数,可以设置套接字的各种属性,如缓冲区大小、超时时间、重传次数等。setsockopt函数的参数包括套接字描述符、协议层、选项名和选项值等。setsockopt函数的返回值为0表示设置成功,否则表示设置失败。setsockopt函数在网络编程中经常被使用,可以帮助程序员实现更加灵活和高效的网络通信。
sockfd:要设置的套接字描述符。
level:选项定义的层次。或为特定协议的代码(如IPv4,IPv6,TCP,SCTP),或为通用套接字代码(SOL_SOCKET)。
optname:选项名。level对应的选项,一个level对应多个选项,不同选项对应不同功能。
optval:指向某个变量的指针,该变量是要设置新值的缓冲区。可以是一个结构体,也可以是普通变量
optlen:optval的长度。

 r = ioctl(*psock, SIOCSIFFLAGS, &ifr);

ioctl

        (input/output control)是 Linux 内核提供的一种设备驱动程序接口,用于控制设备的输入输出操作。它允许用户空间程序与设备驱动程序进行交互,以控制设备的各种特性。常见的例子包括设置网络接口的 IP 地址、设置视频设备的分辨率等。       

        ioctl 是设备驱动程序中设备控制接口函数,一个字符设备驱动通常会实现设备打开、关闭、读、写等功能,在一些需要细分的情境下,如果需要扩展新的功能,通常以增设 ioctl() 命令的方式实现。

        在文件 I/O 中,ioctl 扮演着重要角色,本文将以驱动开发为侧重点,从用户空间到内核空间纵向分析 ioctl 函数。

/* bind socket to protocol, in this case RAW EtherCAT */
struct sockaddr_ll sll;
sll.sll_family = AF_PACKET;
sll.sll_ifindex = ifindex;
sll.sll_protocol = htons(ETH_P_ECAT);
r = bind(*psock, (struct sockaddr *)&sll, sizeof(sll));
/*int bind(int sockfd,const struct sockddr *addr,socklen_t addrlen);
成功返回0,失败返回1
sockfd:socket返回的fd;
addr:struct sockddr的结构体地址(通用结构体,man 7 ip 可查看)
若bind的addr不是具体的一个IP地址,而是INADDR_ANY(宏,值为-1)
则代表bind服务器IP地址为本机的任意网卡地址;
addrlrn:地址长度

  struct sockaddr_in {
               sa_family_t    sin_family; /* address family: AF_INET */(2字节)
               in_port_t      sin_port;   /* port in network byte order */(2字节)
               struct in_addr sin_addr;   /* internet address */(4字节)
           };

           /* Internet address. */
   struct in_addr {
               uint32_t       s_addr;     /* address in network byte order */
           };
*/

绑定端口

int ecx_outframe(ecx_portt *port, int idx, int stacknumber)
{
   int lp, rval;
   ec_stackT *stack;

   if (!stacknumber)
   {
      stack = &(port->stack);
   }
   else
   {
      stack = &(port->redport->stack);
   }
   lp = (*stack->txbuflength)[idx];
   (*stack->rxbufstat)[idx] = EC_BUF_TX;
   rval = send(*stack->sock, (*stack->txbuf)[idx], lp, 0);
   if (rval == -1)
   {
      (*stack->rxbufstat)[idx] = EC_BUF_EMPTY;
   }

   return rval;
}

 代码在nicdrv.c

send()函数

        函数原型:ssize_t send(int sockfd, const void *buf, size_t len, int flags);      

         功能:向套接字中发送数据

        参数:sockfd:向套接字中发送数据

                   buf:要发送的数据的首地址

                   len:要发送的数据的字节

                   int flags:设置为MSG_DONTWAITMSG 时 表示非阻塞

                                   设置为0时 功能和write一样

        返回值:成功返回实际发送的字节数

        失败:返回 -1

static int ecx_recvpkt(ecx_portt *port, int stacknumber)
{
   int lp, bytesrx;
   ec_stackT *stack;

   if (!stacknumber)
   {
      stack = &(port->stack);
   }
   else
   {
      stack = &(port->redport->stack);
   }
   lp = sizeof(port->tempinbuf);
   bytesrx = recv(*stack->sock, (*stack->tempbuf), lp, 0);
   port->tempinbufs = bytesrx;

   return (bytesrx > 0);
}

代码在nicdrv.c

recv()函数

函数原型:ssize_t recv(int sockfd, const void *buf, size_t len, int flags);      

         功能:向套接字中发送数据

        参数:sockfd:在哪个套接字接

                   buf:存放要接收的数据的首地址

                   len:要接收的数据的字节

                   int flags:设置为MSG_DONTWAITMSG 时 表示非阻塞

                                   设置为0时 功能和read一样

        返回值:成功返回实际发送的字节数

        失败:返回 -1
 

你可能感兴趣的:(SOEM,网络,linux,运维)