使用SOCK_RAW时出现套接字错误,以及如何通过第2层通信接受多个客户端 [英] socket error when using SOCK_RAW and how to accept multiple client with layer 2 communication

查看:225
本文介绍了使用SOCK_RAW时出现套接字错误,以及如何通过第2层通信接受多个客户端的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  1. soc = socket(AF_PACKET,SOCK_RAW,htons(ETH_P_ALL));在客户端运行时,会得到== -1错误

  1. soc = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); in client side, when run, get == -1 error

如果accept功能只能与UDP和TCP更高协议一起使用,那么如何通过第2层通信来接受多个客户端?

if accept function can only use with UDP and TCP higher protocol, how to accept multiple client with layer 2 communication?

在哪里可以找到accept函数的代码,我想将其重写为第2层.

where can find the code of accept function, i would like to rewrite it for layer 2.

已更新: 经过尝试soc = socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL)); 也== -1,得到这个错误

Updated : After tried soc = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); also == -1 , get this error

服务器端和客户端都是同一台计算机,本地一台 奇怪的是,正在运行服务器端,它没有此错误,但是正在运行客户端程序却出现了错误

server side and client side both are the same computer, local one strange is that running server side, it do not have this error, but running client program got error

//#include "stdafx.h"

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h> 
#include <arpa/inet.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <net/if.h>
#include <netinet/if_ether.h>
#include <netpacket/packet.h>
#include <net/ethernet.h>
#include <netinet/ether.h>
//#include "sock.h"

#define MAX_MESSAGE          21000
#define FD_NUM 5
#define tcp_port                5009


//#pragma comment(lib, "ws2_32.lib")
//#include <winsock2.h>

char host_ip[16] = "127.0.0.1";

void task()
{
    struct sockaddr_in local;
    int opt;
    int soc;

    //soc = socket(AF_INET,SOCK_STREAM,0);
    soc = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    if (soc==-1) {
        printf("socket error\n");
    }
    // determine ethernet number    
    /*
    struct ifreq ifr;
    size_t if_name_len=strlen(if_name);
    if (if_name_len<sizeof(ifr.ifr_name)) {
        memcpy(ifr.ifr_name,if_name,if_name_len);
        ifr.ifr_name[if_name_len]=0;
    } else {
        printf("interface name is too long");
    }
    if (ioctl(fd,SIOCGIFINDEX,&ifr)==-1) {
        printf("determine ethernet number error\n");
    }
    int ifindex=ifr.ifr_ifindex;
    */
    // mac address
    /*target address*/
    struct sockaddr_ll socket_address;

    /*buffer for ethernet frame*/
    void* buffer = (void*)malloc(ETH_FRAME_LEN);

    /*pointer to ethenet header*/
    unsigned char* etherhead = (unsigned char*)buffer;

    /*userdata in ethernet frame*/
    unsigned char* data = (unsigned char*)buffer + 14;

    /*another pointer to ethernet header*/
    struct ethhdr *eh = (struct ethhdr *)etherhead;

    int send_result = 0;

    /*our MAC address*/
    //10:78:d2:ad:90:cb
    //0x10,0x78,0xD2,0xAD,0x90,0xCB
    unsigned char src_mac[6] = {0x10,0x78,0xD2,0xAD,0x90,0xCB};

    /*other host MAC address*/
    unsigned char dest_mac[6] = {0x10,0x78,0xD2,0xAD,0x90,0xCB};

    /*prepare sockaddr_ll*/

    /*RAW communication*/
    socket_address.sll_family   = PF_PACKET;    
    /*we don't use a protocoll above ethernet layer
      ->just use anything here*/
    socket_address.sll_protocol = htons(ETH_P_IP);  

    /*index of the network device
    see full code later how to retrieve it*/
    socket_address.sll_ifindex  = 0;

    /*ARP hardware identifier is ethernet*/
    socket_address.sll_hatype   = ARPHRD_ETHER;

    /*target is another host*/
    socket_address.sll_pkttype  = PACKET_OTHERHOST;

    /*address length*/
    socket_address.sll_halen    = ETH_ALEN;     
    /*MAC - begin*/
    socket_address.sll_addr[0]  = 0x10;     
    socket_address.sll_addr[1]  = 0x78;     
    socket_address.sll_addr[2]  = 0xD2;
    socket_address.sll_addr[3]  = 0xAD;
    socket_address.sll_addr[4]  = 0x90;
    socket_address.sll_addr[5]  = 0xCB;
    /*MAC - end*/
    socket_address.sll_addr[6]  = 0x00;/*not used*/
    socket_address.sll_addr[7]  = 0x00;/*not used*/

    memcpy((void*)buffer, (void*)dest_mac, ETH_ALEN);
    memcpy((void*)(buffer+ETH_ALEN), (void*)src_mac, ETH_ALEN);
    eh->h_proto = 0x00;

    int j = 0;
    for (j = 46; --j; data[j] = (unsigned char)((int) (255.0*rand()/(RAND_MAX+1.0))));

    /*
    struct sockaddr_in server;
    int len = sizeof(server);
    server.sin_family=AF_INET;
    server.sin_port=htons(5008);
    server.sin_addr.s_addr=inet_addr(host_ip);

    int CONN_SOCK   = InitSocketTcp(tcp_port);
    if(connect(CONN_SOCK, (struct sockaddr*)&server, sizeof(server)) == -1)
    {
        printf("connection failed\n");
    }
    else
    {
            printf("connection ok!\n");
    }
    */
    while(1)
    {
        char buff[492] = "\0";
        printf("input: ");
        scanf("%s", buff);

        //send(CONN_SOCK,buff,strlen(buff),0);
        /*send the packet*/
        send_result = sendto(soc, buff, ETH_FRAME_LEN, 0, (struct sockaddr*)&socket_address, sizeof(socket_address));
        send_result == -1?printf("send error"):0;

        if(buff[0] == 'q')
        {
            //shutdown(CONN_SOCK, SD_SEND);
            //closesocket(CONN_SOCK);
            //WSACleanup();
            close(soc);
            exit(0);
        }
    }
}

int main()
{
    //for(int i=10; i!=0; --i)
        //pthread_create();
    task();
    return 0;
}

推荐答案

Accept()仅用于TCP或UDP(实际上,它的主要用途是在tcp中),因为它建立了连接.一个连接在tcp的情况下进行3次握手,并交换诸如序号等信息,并且完全由套接字(端口加ip地址)标识

Accept() is only used for TCP or UDP (practically it's main use is in tcp), because it establishes a connection. A connection does 3 way handshake in case of tcp and exchanges information such as sequence numbers etc. and is completely identified by a socket (port plus ip address)

与之相反,您可以像在udp情况下通常使用的那样简单地使用api的sendto和receive,其中每个数据包可能遵循不同的路径到达目的地.如果进行udp通讯,则不需要接受.可以将其扩展到链路层(L2)帧,即,每一侧都可以随意发送或接收,而无需先实际建立连接.

In contrast to that you can simply use sendto and receivefrom api's as normally used in case of udp, where each packet may follow a different path to reach destination. You do not require an accept in case of udp communication. The same can be extended to link layer (L2) frames i.e. each side can send or receive at will without actually establishing a connection first.

这应该使用root来完成

This should be done using root

这篇关于使用SOCK_RAW时出现套接字错误,以及如何通过第2层通信接受多个客户端的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆