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这种状态。

相关推荐
安科瑞刘鸿鹏172 小时前
从监测到保护:ALP如何赋能企业配电柜安全升级?
运维·网络·安全
IUGEI2 小时前
深入解析HTTP长连接原理
java·网络·后端·网络协议·tcp/ip·http·https
kkce3 小时前
快快科技 MTR 路由检测全面支持 IPv6,多节点覆盖赋能全协议网络诊断
服务器·网络·科技
acrel158215962213 小时前
新品!分布式新能源群调群控装置!ANet-4E16S-AGVC 装置让分布式发电更智能、更高效
网络·安科瑞电气·分布式新能源群调群控装置·微电网能源管理
zbtlink3 小时前
企业级路由器双网接入指南:实现高效稳定的网络融合
网络
ifeng09184 小时前
HarmonyOS网络请求优化实战:智能缓存、批量处理与竞态处理
网络·缓存·harmonyos
llilian_165 小时前
智能数字式毫秒计在实际生活场景中的应用 数字式毫秒计 智能毫秒计
大数据·网络·人工智能
武汉唯众智创5 小时前
职业院校网络安全靶场实训演练系统建设方案
网络·安全·web安全·网络安全·网络安全靶场实训演练系统·网络安全靶场实训·网络安全实训演练系统
G31135422735 小时前
判断 IP 地址纯净度
服务器·网络
喵手5 小时前
网络编程:Java中的TCP与UDP通信!
java·udp·网络编程·tcp