c - 使用原始套接字接收

标签 c sockets recv

我试图从套接字接收原始数据包但失败了。只有在服务器站点上发送数据包时才会打印消息。当没有数据包传输时 - 程序卡在 recv 中(同步模式下的套接字)。

问题是打印消息是“缓冲区”但没有收到数据。

#include <sys/socket.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>

#define ETH_FRAME_LEN 1400

int main(){

    int s; /*socketdescriptor*/

    s = socket(PF_PACKET, SOCK_RAW, htons(0x88b5));
    if (s == -1) { perror("socket"); }

        struct sockaddr_ll socket_address;
    int r;
    char ifName[IFNAMSIZ] = "eth0";

    struct ifreq ifr;  
        strncpy((char *)ifr.ifr_name ,device , IFNAMSIZ); 

    /* Get the index of the interface to send on */
    memset(&if_idx, 0, sizeof(struct ifreq));
    strncpy(if_idx.ifr_name, ifName, IFNAMSIZ-1);
    if (ioctl(sockfd, SIOCGIFINDEX, &if_idx) < 0)
        perror("SIOCGIFINDEX");

    /* Get the MAC address of the interface to send on */   
    memset(&if_mac, 0, sizeof(struct ifreq));
    strncpy(if_mac.ifr_name, ifName, IFNAMSIZ-1);
    if (ioctl(sockfd, SIOCGIFHWADDR, &if_mac) < 0)
        perror("SIOCGIFHWADDR");

        memset(&socket_address, 0, sizeof(socket_address));
        socket_address.sll_ifindex = ifr.if_idx;
        socket_address.sll_protocol = htons(0x88b5);
        socket_address.sll_family = PF_PACKET;
        socket_address.sll_pkttype = PACKET_OUTGOING;

        r = bind(s, (struct sockaddr*)&socket_address,
                    sizeof(socket_address));
    if ( r < 0) { perror("bind")};

    void* buffer = (void*)malloc(ETH_FRAME_LEN); /*Buffer for ethernet frame*/
    int length = 0; /*length of the received frame*/ 

    length = recv(s, buffer, ETH_FRAME_LEN, 0,);
    if (length == -1) { perror("recvfrom"); }
    printf ("buffer %s\n", buffer);

}

最佳答案

您只能对 C 风格的字符串使用 %s 格式说明符。您不能将它用于任意二进制数据。它怎么知道要打印多少个字符?您在名为 length 的变量中有长度。您需要打印那么多字符。例如:

for (int i = 0; i < length; ++i)
     putchar(((char *)buffer)[i]);

这可能看起来像垃圾,因为您正在输出一堆不可打印的字符。也许你想要这样的东西:

void print(void *buf, int length)
{
      char *bp = (char *) buf;
      for (int i = 0; i < length; ++i)
          putchar( isprintf(bp[i]) ? bp[i] : '.' );
      putchar('\n');
}

这将用点替换不可打印的字符。

关于c - 使用原始套接字接收,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15092397/

相关文章:

java - 带有序列号的 UDP

c - 为什么服务器在客户端应用程序处于 STOPPED 状态后等待客户端?

linux - Linux AIO 是否支持 RAW 套接字?

multithreading - 如何使用单个端口处理多个逻辑数据流(Winsock)?

c - 从内核分配用户空间内存

c++ - 为数组赋值时是否存在性能差异

c - 使用 libsndfile 为 MATLAB 编写多 channel 音频

delphi - 什么会导致套接字在每次 HTTP 事务后快速关闭?

C - 使用 sin_addr 获取 IP 地址字符串

c - 每次登录时为服务器分配静态/相同的 IP 地址