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

相关推荐
代码中介商5 小时前
Linux TCP 网络编程完全指南:从三次握手到高并发服务器
服务器·网络·tcp/ip
咖喱o5 小时前
QinQ/VLAN Stacking
linux·运维·服务器·网络
AI周红伟7 小时前
周红伟:运营商一季度净利集体下滑 Token运营提速
大数据·网络·人工智能
marsh02067 小时前
43 openclaw熔断与降级:保障系统在异常情况下的可用性
java·运维·网络·ai·编程·技术
汽车仪器仪表相关领域8 小时前
Kvaser Memorator Professional 5xHS CB:五通道CAN FD裸板记录仪,赋能多总线系统集成测试的旗舰级核心装备
大数据·网络·人工智能·单元测试·汽车·集成测试
初学者,亦行者8 小时前
计算机网络必考:一文吃透 TCP/IP 体系结构(附高清思维导图)
网络·tcp/ip
段一凡-华北理工大学9 小时前
【高炉炼铁领域炉温监测、预警、调控智能体设计与应用】~系列文章10:实时预警机制:跑在问题前面!
网络·人工智能·python·知识图谱·高炉炼铁·工业智能体
WJ.Polar9 小时前
Scapy基本应用
linux·运维·网络·python
@insist1239 小时前
信息安全工程师-入侵检测核心技术、APT 应对与工程实践
网络·安全·软考·信息安全工程师·软件水平考试
CDN36010 小时前
[硬核] 你的DNS正在“裸奔”?用Python手撕DNS劫持与隧道检测逻辑
开发语言·网络·python