Мой вопрос связан с использованием флага IP_HDRINCL
в setsockopt
. Я пытаюсь проверить использование пользовательского протокола с необработанными сокетами. Я не уверен, правильно ли то, что я делаю. Я просто пытаюсь передать строку в код сервера вместе с заголовком ip, прикрепленным клиентским кодом. Первый код, который я написал, был:
Server.c
#include "../cn.h"
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
int main(int argc, char const *argv[])
{
int rsfd = socket(AF_INET,SOCK_RAW,253);
if(rsfd<0)
{
perror("Could not create socket");exit(0);
}
int val = 1;
setsockopt(rsfd,IPPROTO_IP,SO_BROADCAST|IP_HDRINCL,&val,sizeof(val));
char buffer[100];
struct iphdr *ip;
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.2");
if(bind(rsfd,(struct sockaddr*)&addr,sizeof(addr))<0)
{
perror("Could not bind");exit(0);
}
else
printf("Bound..\n");
if(recvfrom(rsfd,buffer,100,0,NULL,NULL)<0)
{
perror("Could not receive");exit(0);
}
else
{
printf("Success..\n");
ip = (struct iphdr*)(buffer);
char ad[INET_ADDRSTRLEN];
printf("Protocol No: %d\nTTL: %d\nVersion No: %d\nPacket ID: %d\nSource Address: %s\nChecksum: %d\nLength: %d\n",(int)ip->protocol,(int)ip->ttl,(int)ip->version,(int)ip->id,inet_ntop(AF_INET,&(ip->saddr),ad,INET_ADDRSTRLEN),(int)ip->check,(int)ip->ihl);
}
return 0;
}
Client.c
#include "../cn.h"
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
int main(int argc, char const *argv[])
{
int rsfd = socket(AF_INET,SOCK_RAW,253);
if(rsfd<0)
{
perror("Could not create socket");exit(0);
}
int val = 1;
setsockopt(rsfd,IPPROTO_IP,SO_BROADCAST|IP_HDRINCL,&val,sizeof(val));
char buffer[100];
struct iphdr* ip;
ip = (struct iphdr*)buffer;
ip->protocol = 253;
ip->version = 4;
ip->id = 0;
ip->saddr = 0;
ip->daddr = inet_addr("127.0.0.2");
printf("Enter a string..\n");
scanf("%s",buffer+60); //trying to insert a string at buffer+60 position
printf("Entered: %s\n",buffer+60);
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.2");
if(sendto(rsfd,buffer,100,0,(struct sockaddr*)&addr,sizeof(addr))<0)
perror("Could not send");
else
printf("Sent successfully..\n");
return 0;
}
Программа работает без ошибок, но когда я попытался напечатать сообщение со смещением 60, оно набрало какое-то мусорное значение. Затем я попытался напечатать все значения в этом символьном буфере, и, к моему изумлению, фактическое сообщение было со смещением 80, что означает ровно 20 байтов от места, где я его вставил. Проведя еще несколько экспериментов, я понял, что этот заголовок ip
, полученный на стороне сервера, вообще не является определяемым пользователем заголовком. Это связано с самим сетевым уровнем! Но разве опция IP_HDRINCL
не должна удерживать сетевой уровень от присоединения заголовка ip? Я говорю это на основании того, что я истолковал из этого . Где я делаю ошибку? Кроме того, кто-нибудь может предоставить несколько хороших руководств по необработанным сокетам (особенно по реализации пользовательских протоколов)?