gpt4 book ai didi

c - 使用 SOCK_RAW 时的套接字错误以及如何接受具有第 2 层通信的多个客户端

转载 作者:太空宇宙 更新时间:2023-11-04 04:00:22 27 4
gpt4 key购买 nike

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

  2. 如果accept函数只能与UDP和TCP高层协议(protocol)一起使用,如何接受多个二层通信的client?

哪里可以找到accept函数的代码,我想为layer 2重写。

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

服务器端和客户端都是同一台电脑,本地一台奇怪的是在服务端运行没有这个错误,但是在客户端运行就报错了

//#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 地址)标识

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

这应该使用 root 来完成

关于c - 使用 SOCK_RAW 时的套接字错误以及如何接受具有第 2 层通信的多个客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12435958/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com