TCP与UDP可以绑定再相同的IP与端口上互不影响

复制代码
#include <sys/epoll.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <unistd.h>

#include <fcntl.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <errno.h>



#define MAX_EVENTS 10

#define BUFFER_SIZE 1024

#define PORT 8888



void set_nonblocking(int fd) {

    int flags = fcntl(fd, F_GETFL, 0);

    fcntl(fd, F_SETFL, flags | O_NONBLOCK);

}



int main() {

    int tcp_sock, udp_sock, epoll_fd;

    struct epoll_event ev, events[MAX_EVENTS];

   

    // 创建TCP套接字

    if ((tcp_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {

        perror("TCP socket");

        exit(EXIT_FAILURE);

    }



    // 创建UDP套接字

    if ((udp_sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {

        perror("UDP socket");

        close(tcp_sock);

        exit(EXIT_FAILURE);

    }



    // 设置地址重用

    int opt = 1;

    setsockopt(tcp_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    setsockopt(udp_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));



    struct sockaddr_in addr = {

        .sin_family = AF_INET,

        .sin_addr.s_addr = INADDR_ANY,

        .sin_port = htons(PORT)

    };



    // 绑定TCP

    if (bind(tcp_sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) {

        perror("TCP bind");

        close(tcp_sock);

        close(udp_sock);

        exit(EXIT_FAILURE);

    }



    // 绑定UDP

    if (bind(udp_sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) {

        perror("UDP bind");

        close(tcp_sock);

        close(udp_sock);

        exit(EXIT_FAILURE);

    }



    // 监听TCP

    if (listen(tcp_sock, SOMAXCONN) == -1) {

        perror("TCP listen");

        close(tcp_sock);

        close(udp_sock);

        exit(EXIT_FAILURE);

    }



    // 创建epoll实例

    epoll_fd = epoll_create1(0);

    if (epoll_fd == -1) {

        perror("epoll_create1");

        close(tcp_sock);

        close(udp_sock);

        exit(EXIT_FAILURE);

    }



    // 添加TCP到epoll

    ev.events = EPOLLIN;

    ev.data.fd = tcp_sock;

    epoll_ctl(epoll_fd, EPOLL_CTL_ADD, tcp_sock, &ev);



    // 添加UDP到epoll(非阻塞)

    set_nonblocking(udp_sock);

    ev.events = EPOLLIN | EPOLLET;

    ev.data.fd = udp_sock;

    epoll_ctl(epoll_fd, EPOLL_CTL_ADD, udp_sock, &ev);



    printf("Server started on TCP/UDP port %d\n", PORT);



    while (1) {

        int nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);

        if (nfds == -1) {

            perror("epoll_wait");

            break;

        }



        for (int i = 0; i < nfds; ++i) {

            if (events[i].data.fd == tcp_sock) {

                // 处理TCP连接

                struct sockaddr_in client_addr;

                socklen_t addrlen = sizeof(client_addr);

                int conn_sock = accept(tcp_sock, (struct sockaddr*)&client_addr, &addrlen);

                if (conn_sock == -1) {

                    perror("TCP accept");

                    continue;

                }



                set_nonblocking(conn_sock);

                ev.events = EPOLLIN | EPOLLET;

                ev.data.fd = conn_sock;

                epoll_ctl(epoll_fd, EPOLL_CTL_ADD, conn_sock, &ev);

                printf("New TCP connection: %d\n", conn_sock);

            }

            else if (events[i].data.fd == udp_sock) {

                // 处理UDP数据

                struct sockaddr_in client_addr;

                socklen_t addrlen = sizeof(client_addr);

                char buffer[BUFFER_SIZE];

               

                while (1) {

                    ssize_t bytes_recv = recvfrom(udp_sock, buffer, BUFFER_SIZE, 0,

                                                (struct sockaddr*)&client_addr, &addrlen);

                    if (bytes_recv <= 0) {

                        if (errno == EAGAIN || errno == EWOULDBLOCK) break;

                        perror("UDP recv");

                        break;

                    }

                   

                    printf("Received %zd UDP bytes\n", bytes_recv);

                    sendto(udp_sock, buffer, bytes_recv, 0,

                        (struct sockaddr*)&client_addr, addrlen);

                }

            }

            else {

                // 处理TCP客户端数据

                char buffer[BUFFER_SIZE];

                ssize_t bytes_read;

                int fd = events[i].data.fd;

               

                while ((bytes_read = read(fd, buffer, BUFFER_SIZE)) > 0) {

                    write(fd, buffer, bytes_read);

                }



                if (bytes_read == 0 || (bytes_read == -1 && errno != EAGAIN)) {

                    printf("TCP connection closed: %d\n", fd);

                    close(fd);

                    epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, NULL);

                }

            }

        }

    }



    close(tcp_sock);

    close(udp_sock);

    close(epoll_fd);

    return 0;

}

查看端口的时候我发现并不冲突,UDP是无连接的因此不会有listen和established这种状态。

相关推荐
molaifeng4 小时前
Go 语言如何实现高性能网络 I/O:Netpoller 模型揭秘
开发语言·网络·golang
知乎的哥廷根数学学派5 小时前
基于多模态特征融合和可解释性深度学习的工业压缩机异常分类与预测性维护智能诊断(Python)
网络·人工智能·pytorch·python·深度学习·机器学习·分类
网络工程师_ling5 小时前
【 Elastiflow (ELK) 网络流量分析系统 部署教程】
网络·elk
2301_780789666 小时前
高防 IP 的选择与配置确保业务稳定性
网络·网络协议·tcp/ip
willhuo6 小时前
基于xray的匿名、授权、IP白名单代理访问研究
服务器·网络·tcp/ip
qiuqyue6 小时前
基于虹软Linux Pro SDK的多路RTSP流并发接入、解码与帧级处理实践
linux·运维·网络
无名3876 小时前
关于 VRF
网络·通信
YounGp_oo7 小时前
一次内网开发环境访问方式的改进实践:使用 FRP 替代远程桌面
网络·ssh·frp·内网穿透·开发环境
云安全干货局7 小时前
服务器被攻击后如何快速恢复?数据备份 + 应急响应手册
网络·网络安全·云服务器·弹性云服务器
猿饵块7 小时前
tcp--抓包--wireshark
网络·测试工具·wireshark