刚学习LINUX网络编程,关于一个UDP的问题想请教一下大家

Sec_killer 2018-04-06 12:08:19
本人才学LINUX编程 想写一个辅助程序来穿透NAT 客户端请求后 返回客户端的IP和地址,但发现程序运行一下就出现假死的情况,请各位大神帮忙分析一下,附代码:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <assert.h>
#include <signal.h>

void epool_process(int epoll_fd, int fd) {
char buf[64] = { 0 };
struct sockaddr_in from;
int ret = 0;
socklen_t fromlen = sizeof(from);
ret = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&from, &fromlen);
if (ret > 0) {
//回复6个字节的数据包 前4字节是IP 后2字节是端口号
*(int *)buf = from.sin_addr.s_addr;
*(u_short*)(char *)(buf + 4) = from.sin_port;
sendto(fd, buf, 6, 0, (struct sockaddr *)&from, fromlen);
}

//关闭清理
struct epoll_event event;
event.data.fd = fd;
event.events = EPOLLOUT;
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &event);

close(fd);
printf("pid:%d --> %s:%d\n", getpid(), inet_ntoa(from.sin_addr), htons(from.sin_port));
}

int main(int argc, char* argv[]) {

int fd = 0;
pid_t pid;
struct sockaddr_in local;

//忽略子进程信号,避免产生僵尸进程
signal(SIGCHLD, SIG_IGN);

local.sin_family = AF_INET;
local.sin_port = htons(1080);
local.sin_addr.s_addr = htonl(INADDR_ANY);

//创建一个UDP的fd
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd == 0)
exit(1);

//绑定一个UDP端口
if (bind(fd, (struct sockaddr *)&local, sizeof(local)) < 0)
exit(-1);

//创建epoll事件
struct epoll_event event;
struct epoll_event wait_event;

//创建一个epoll的句柄 参数要大于0 没有太大意义
int epoll_fd = epoll_create(10);
if (epoll_fd == -1)
return -1;

//把socks句柄加入监听事件
event.data.fd = fd;
event.events = EPOLLIN; //表示对应的文件描述符可以读(包括对端 SOCKET 正常关闭);
//event.events |= EPOLLET;
//当 epoll_wait 检测到描述符事件发生并将此事件通知应用程序,应用程序必须立即处理该事件。如果不处理,下次调用 epoll_wait 时,不会再次响应应用程序并通知此事件。

int ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &event);
if (ret == -1)
return -1;

//因为使用ET模式 所以必须设置为非阻塞模式
//int flags = fcntl(fd, F_GETFL);
//fcntl(fd, F_SETFL, flags | O_NONBLOCK);

while (1) {
ret = epoll_wait(epoll_fd, &wait_event, 1, -1);

if (ret == -1) {
printf("epoll_wait errno\n");
close(epoll_fd);
return 0;
}
else if (ret > 0) {
if ((wait_event.data.fd == fd) && //UDP
(wait_event.events & EPOLLIN == EPOLLIN)) {
pid = fork();
if (pid == -1) {
printf("fork errno!\n");
continue;
}
if (pid == 0) {
epool_process(epoll_fd, fd);
exit(EXIT_SUCCESS);
}
}
}
}

return 0;
}
...全文
860 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
dark9527 2018-05-07
  • 打赏
  • 举报
回复
主函数的while循环中没有包含添加udp fd到epoll监听队列的代码,在子函数中清理后无法监听了。
金秋枣香 2018-04-11
  • 打赏
  • 举报
回复
epoll控制udp,就是每次都是一个新的连接过来。 代码问题在于,//关闭清理 struct epoll_event event; event.data.fd = fd; event.events = EPOLLOUT; epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &event); close(fd); 将这段代码注释掉就可以了。
jklinux 2018-04-11
  • 打赏
  • 举报
回复
引用 3 楼 u014709236 的回复:
感谢2楼的回复 我在发送20多个包后 发送程序也会被阻塞,但是明显是这个服务程序的问题,然后这个程序就会很长时间无法收到外面发过来的包 所以肯定这段代码会有问题 希望有热心的朋友帮忙看看
epoll一般是用于tcp服务器端,同时处理多个客户端的网络通信使用的。 而udp是无连接的,不管多少个发送端,接收端都是用recvfrom就可以了。还没试过用epoll监控udp的socket文件描述符呢(理论上是可以的)
Sec_killer 2018-04-10
  • 打赏
  • 举报
回复
感谢2楼的回复 我在发送20多个包后 发送程序也会被阻塞,但是明显是这个服务程序的问题,然后这个程序就会很长时间无法收到外面发过来的包 所以肯定这段代码会有问题 希望有热心的朋友帮忙看看
jklinux 2018-04-08
  • 打赏
  • 举报
回复
这个程序还需要有其它网络端发udp数据包过来才可以的,没有接收到数据, 这程序就会一直堵塞了
Sec_killer 2018-04-06
  • 打赏
  • 举报
回复
补充:希望大家可以把我代码的所有问题找出来,还有如何防范恶意请求消耗服务器资源

23,116

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧