当前位置: 首页 > 知识库问答 >
问题:

无法接收到原始套接字的数据包

宋伟泽
2023-03-14

我正在编写原始套接字客户端(成功发送UDP数据包)和一个服务器套接字,问题出在服务器部分。

Im按以下方式创建套接字:

int raw_socket=套接字(AF_INET,SOCK_RAW,IPPROTO_UDP);

#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
int server(){
    int raw_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
    if (raw_socket== -1){
        perror("Socket_creation_error\n");
        return 1;
    }

    struct sockaddr_in sockstr;
    sockstr.sin_addr.s_addr = inet_addr("127.0.0.1");
    sockstr.sin_family = AF_INET;
    sockstr.sin_port = htons(9090);
    socklen_t s = (socklen_t)sizeof(sockstr);

    if (bind(raw_socket, (struct sockaddr*)&sockstr, sizeof(sockstr))< 0){
        perror("binding_err\n");
        return 0;
    }
    char* msg[256];
    memset(msg, 0, 256);

    recv(raw_socket, msg, sizeof(msg), 0);
    printf(msg);
    return 0;
}

void main(){
    server();
}

共有1个答案

宗政霄
2023-03-14

正如raw套接字手册中所说的user@host:~$man 7 raw:

IPROTO_RAW的协议意味着启用了IP_HDRINCL,并且能够发送在所传递的报头中指定的任何IP协议。使用原始套接字无法通过IPPROTO_RAW接收所有IP协议。

另一个同样摘自《手册》的重要注意事项是:

  • 上面的代码中缺少一些#include...标头。
  • ipproto_raw(如手册所述)不能用于接收所有协议。
  • 你为什么要给Socklen下定义?例如,您可以在bind()中使用它。
  • char*msg[SIZE]???? · · 这是一个字符指针数组!您只需要一个字符数组,如下所示:char msg[SIZE].
  • 记住,您使用的是原始套接字,从这些套接字接收的数据包带有报头。要打印您的消息,您需要在msg中做一个偏移量,它对应于ip头加上upd头。(在下面的代码中,请注意,我添加了#include #include 以获得头的大小)。
  • 最后,进行清理:在本例中,只关闭()套接字:-)

main.c

#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>

#include <linux/ip.h> /* for ipv4 header */
#include <linux/udp.h> /* for upd header */

#define ADDR_TO_BIND "127.0.0.1"
#define PORT_TO_BIND 9090

#define MSG_SIZE 256
#define HEADER_SIZE (sizeof(struct iphdr) + sizeof(struct udphdr))

int main(void) {
    int raw_socket;
    struct sockaddr_in sockstr;
    socklen_t socklen;

    int retval = 0; /* the return value (give a look when an error happens)
                     */

    /* no pointer to array!
     * >> It was like "a variable that contains an address -- and in this
     *    address begins an array of chars"! */
    /* now it is simple an array of chars :-)  */
    char msg[MSG_SIZE];
    ssize_t msglen; /* return value from recv() */

    /* do not use IPPROTO_RAW to receive packets */
    if ((raw_socket = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) == -1) {
        perror("socket");
        return 1; /* here there is no clean up -- retval was not used */
    }

    sockstr.sin_family = AF_INET;
    sockstr.sin_port = htons(PORT_TO_BIND);
    sockstr.sin_addr.s_addr = inet_addr(ADDR_TO_BIND);
    socklen = (socklen_t) sizeof(sockstr);

    /* use socklen instead sizeof()  Why had you defined socklen? :-)  */
    if (bind(raw_socket, (struct sockaddr*) &sockstr, socklen) == -1) {
        perror("bind");
        retval = 1; /* '1' means "Error" */
        goto _go_close_socket;
    }

    memset(msg, 0, MSG_SIZE);

    if ((msglen = recv(raw_socket, msg, MSG_SIZE, 0)) == -1) {
        perror("recv");
        retval = 1;
        goto _go_close_socket;
    }

    if (msglen <= HEADER_SIZE) /* msg  can't be lesser than header! */
        printf("No msg!\n");
    else {
        msg[msglen - 1] = '\0'; /* we need a null character at the end*/
        printf("Your msg _plus_ headers's size is: %s\n",
               msg + HEADER_SIZE);
    }

_go_close_socket:
    close(raw_socket);

    return retval;
}

好了,现在用:
user@host:~$gcc-o main main.c以root:
root@host:~#./main的身份执行程序,并在另一个终端中用nc:
    -u指定UPD到nc
user@host:~$nc-u 127.0.0.1 9090发送消息

 类似资料:
  • 我试着做一个简单的服务器-客户机套接字通信,但服务器似乎无法正常工作。无论何时发送或接收,我都会收到此错误: 非插座上的插座操作:非插座上的插座操作 奇怪的是,这只会在服务器发送时出现。客户似乎还可以:

  • 我有一个游戏,我正在用一些网络来制作多人游戏。我创建了一个自定义模块(在任何方面都不是最好的),将两个值(XY)从-1048576转换为1048576,一个值从0到60(健康),转换为6个字符。所以我可以用6个字节发送所有的信息。 但是这在Python 2中工作,在Python 3中,我发现我不能发送带有字符的“str”,所以我在发送之前使用了“. encode()”,在我的任何函数中使用“. d

  • 我试图创建一个Unix套接字数据报示例。客户端可以流畅地发送和接收消息。在缓冲区长度小于< code>SOCKET_BUFFER_SIZE的情况下,服务器能够做到这一点,否则服务器的输出会在接收的缓冲区显示一些无效字符。 客户代码 服务器的代码 头文件 这是我得到的 奇怪的是,客户端收到了预期的消息,尽管服务器在发送之前没有正确格式化消息。 这是我的预期输出 我该如何解决?

  • 因此,我正在用Java编写一个程序,在DatagramSocket和DataGramPacket的帮助下发送和接收数据。问题是,当我发送数据/接收数据时,数据在我发送的程序中也会有所不同,但只是在某些情况下,比如: 但有时会起作用,比如:

  • 当我尝试接收大量数据时,它会被切断,我必须按enter键才能获取其余数据。起初,我可以增加一点,但它仍然不会收到所有的。正如您所看到的,我增加了conn.recv()上的缓冲区,但它仍然无法获取所有数据。它会在某一点切断它。我必须在原始输入上按enter键才能接收其余数据。我是否可以一次获取所有数据?这是密码。

  • 我使用Android应用程序通过TCP套接字与同一局域网上的PC java应用程序进行通信、发送和接收消息。下面是我在android中使用的Asynctask的代码,用于发送消息并从PC接收回复: } 我在onPostExcecute中的祝酒词中显示PC的回复。 Android通过BufferedWriter发送消息,而PC上的java应用程序在BufferedReader中接收消息。 PC在收到