Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Can';无法将数据包接收到原始套接字_C_Sockets_Udp_Raw Sockets - Fatal编程技术网

Can';无法将数据包接收到原始套接字

Can';无法将数据包接收到原始套接字,c,sockets,udp,raw-sockets,C,Sockets,Udp,Raw Sockets,我正在编写原始套接字客户端(它成功地发送UDP数据包)和服务器套接字,问题在于服务器部分 我正在以以下方式创建套接字: int-raw\u-socket=socket(AF\u-INET、SOCK\u-raw、IPPROTO\u-UDP) 我还尝试了IPPROTO_RAW,但得到了相同的结果,我正在绑定它: bind(原始套接字,(结构sockaddr*)和sockstr,sizeof(sockstr)) 当尝试使用套接字接收某些数据包时,我收到的唯一有效负载是“E”(我认为这意味着“Error

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

我正在以以下方式创建套接字:

int-raw\u-socket=socket(AF\u-INET、SOCK\u-raw、IPPROTO\u-UDP)

我还尝试了IPPROTO_RAW,但得到了相同的结果,我正在绑定它:

bind(原始套接字,(结构sockaddr*)和sockstr,sizeof(sockstr))

当尝试使用套接字接收某些数据包时,我收到的唯一有效负载是“E”(我认为这意味着“Error”),或者套接字继续侦听,但阻塞了,什么也没有发生。 如何使用原始套接字接收UDP数据包? 我的代码:

#包括
#包括
#包括
#包括
#包括
int服务器(){
int raw_socket=插座(AF INET、SOCK_raw、IPPROTO_raw);
if(原始插槽==-1){
perror(“套接字创建错误”);
返回1;
}
sockstr中的结构sockaddr_;
sockstr.sin_addr.s_addr=inet_addr(“127.0.0.1”);
sockstr.sin_family=AF_INET;
sockstr.sinu端口=htons(9090);
socklen_t s=(socklen_t)sizeof(sockstr);
if(绑定(原始套接字,(结构sockaddr*)和sockstr,sizeof(sockstr))<0{
perror(“绑定错误”);
返回0;
}
char*msg[256];
memset(msg,0,256);
recv(原始插座,msg,sizeof(msg),0);
printf(msg);
返回0;
}
void main(){
服务器();
}

如原始插座手册所述
user@host:~$man 7原始版本

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

另一个从手册中摘录的重要注意事项是:

只有有效用户ID为0或CAP\u NET\u RAW功能的进程才允许打开RAW套接字。

手册上也说:

从Linux 2.2开始,可以使用IP套接字选项设置所有IP头字段和选项。这意味着原始套接字通常仅用于新协议或没有用户界面的协议(如ICMP)。

好的,假设您需要准备好IP/UPD头,让我们开始工作:-)

首先,我们需要澄清以下几点:

  • 在上面的代码中,缺少一些
    #include…
    标题
  • IPPROTO_RAW(如手册所述)不能用于接收所有协议
  • 你为什么给索克伦下定义?例如,您可以在bind()中使用它
  • char*msg[SIZE]
    ???这是一个字符指针数组!您只需要一个字符数组,如下所示:
    charmsg[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;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包含/*用于ipv4标头*/
#包括/*用于upd标头*/
#定义添加到绑定“127.0.0.1”
#定义端口\u到\u绑定9090
#定义MSG_大小256
#定义标题大小(sizeof(struct iphdr)+sizeof(struct udphdr))
内部主(空){
int raw_插座;
sockstr中的结构sockaddr_;
socklen_t socklen;
int retval=0;/*返回值(发生错误时查看)
*/
/*没有指向数组的指针!
*>>就像“一个包含地址的变量——在这个
*地址以字符数组开头“*/
/*现在它是一个简单的字符数组:-)*/
char msg[msg_SIZE];
ssize_t msglen;/*recv()的返回值*/
/*不要使用IPPROTO_RAW来接收数据包*/
if((原始套接字=套接字(AF\U INET、SOCK\U raw、IPPROTO\U UDP))=-1){
佩罗(“插座”);
return 1;/*此处没有清理--未使用retval*/
}
sockstr.sin_family=AF_INET;
sockstr.sin\u port=htons(端口到端口绑定);
sockstr.sin_addr.s_addr=inet_addr(addr_TO_BIND);
socklen=(socklen_t)sizeof(sockstr);
/*使用socklen代替sizeof()为什么定义socklen?:-)*/
if(绑定(原始套接字,(结构sockaddr*)和sockstr,socklen)=-1){
佩罗(“绑定”);
retval=1;/*“1”表示“错误”*/
上下合插座;
}
memset(msg,0,msg_大小);
如果((msglen=recv(原始插槽,消息,消息大小,0))=-1){
perror(“recv”);
retval=1;
上下合插座;
}

如果(msglen)如果你在linux和ufw(unix防火墙)上运行UDP数据包被默认删除,也许你想让我们看看你写了什么?什么是“E”?你如何得到“E”?你应该发布一篇文章,告诉我们程序是在哪个系统/权限上运行的。Pritay,我已经编辑了文章并添加了代码。谢谢你的详细解释。这非常有帮助。
#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;
}