Can';无法将数据包接收到原始套接字
我正在编写原始套接字客户端(它成功地发送UDP数据包)和服务器套接字,问题在于服务器部分 我正在以以下方式创建套接字: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
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;
}