以太网传输时字节顺序的变化

时间:2018-05-18 10:01:26

标签: c vivado zynq

我使用zedboard和vivado v2017.3。我试图在以下程序中发送存储在baseaddr_p指向的寄存器(Zynq的PL部分中的slv_reg0)中的数据。

我使用lwip echo服务器应用程序读取此地址并通过以太网将其发送到PC。

这部分代码是在收到回应请求(telnet)时执行的。在这部分代码中,我还打印了gtkterm中的读取值,以便我可以验证接收到的数据。

void process_echo_request(void *p)
{
    int sd = (int)p;
    int RECV_BUF_SIZE = 2048;
    char recv_buf[RECV_BUF_SIZE];
    int n,i,nwrote;
    unsigned long my_buffer[10];
    i=0;
    init_platform();
    while(1){
    while(i<11)
    {
    Xuint32 *baseaddr_p = (Xuint32 *)XPAR_MYIP_0_S00_AXI_BASEADDR;
    my_buffer[i] = *(baseaddr_p);
    xil_printf("0x%08x \n\r", my_buffer[i]);
    i++;}
    //xil_printf("0x%08x \n\r", my_buffer);
     /* handle request */
    if ((nwrote = write(sd, my_buffer, sizeof (my_buffer))) < 0) {
        xil_printf("%s: ERROR responding to client echo request. received = %d, written = %d\r\n",
                __FUNCTION__, n, nwrote);
        xil_printf("Closing socket %d\r\n", sd);
     break;

    }

    while (1) {
        /* read a max of RECV_BUF_SIZE bytes from socket */
        if ((n = read(sd, recv_buf, RECV_BUF_SIZE)) < 0) {
            xil_printf("%s: error reading from socket %d, closing socket\r\n", __FUNCTION__, sd);
            break;
        }

        /* break if the recved message = "quit" */
        if (!strncmp(recv_buf, "quit", 4))
            break;

        /* break if client closed connection */
        if (n <= 0)
            break;


        }
    }

    /* close connection */
    close(sd);
    vTaskDelete(NULL);
    cleanup_platform();
}

gtkterm结果:读取值 0x00000004 0x00000005 0x00000006 0x00000007 0x00000008 0x00000009 0X0000000A 0x0000000B 0x0000000C 0x0000000D 0x0000000E

在接收这些数据时,似乎发生了字节反转。

收到的数据: 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00 08 00 00 00 09 00 00 00 0 00 00 00 0 00 00 00 00 0C 00 00 00 0D 00 00 00

有关其发生原因和可能的解决方法的任何建议吗?

2 个答案:

答案 0 :(得分:3)

问题归因于endianess。当您发送和接收数据时,最好是主机进行网络转换,反之亦然。

有两个POSIX API可以执行这些字节顺序转换:htonlntohl

在接收方尝试进行网络主机字节顺序转换,如果你有权访问发送方,那就相反。

答案 1 :(得分:2)

您的源计算机对整数使用little-endian内部表示。它的lui, ori, lw, lui, ori, lw函数解释了这一点,以规范的方式为人类消费格式化数字。字节交换是那里,它是良性的。

另一方面,xil_printf()并不了解或关心您所掌握的数据的重要性。它将所有内容简单地视为一个字节序列,并按照它们出现的顺序传输它们。类似地,write()函数按照它们通过线路的顺序接收和存储字节。那里没有字节交换。

如果您可以依赖接收数据的机器根据相同的数字格式(大小,字节顺序等)来解释它,那么就没有问题。如果没有,那么您需要将数据放入标准格式以通过线路传输,或者发送源机器格式的一些指示符,接收器应该适当地处理。

前一种方法更为常见。事实上,这是POSIX定义的the htonl() and ntohl() functions的作用。如果你没有那些,那么他们自己并不太难实现 - 最大的伎俩(而且 大)并不是确定原生字节顺序。