刚学习LINUX网络编程,关于一个UDP的问题想请教一下大家
本人才学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;
}