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

相关推荐
blasit2 天前
笔记:Qt C++建立子线程做一个socket TCP常连接通信
c++·qt·tcp/ip
DianSan_ERP7 天前
电商API接口全链路监控:构建坚不可摧的线上运维防线
大数据·运维·网络·人工智能·git·servlet
呉師傅7 天前
火狐浏览器报错配置文件缺失如何解决#操作技巧#
运维·网络·windows·电脑
gihigo19987 天前
基于TCP协议实现视频采集与通信
网络协议·tcp/ip·音视频
2501_946205527 天前
晶圆机器人双臂怎么选型?适配2-12寸晶圆的末端效应器有哪些?
服务器·网络·机器人
linux kernel7 天前
第七部分:高级IO
服务器·网络
数字护盾(和中)7 天前
BAS+ATT&CK:企业主动防御的黄金组合
服务器·网络·数据库
~远在太平洋~7 天前
Debian系统如何删除多余的kernel
linux·网络·debian
龙仔7257 天前
在麒麟V10服务器安全加固,sshd防暴力破解加固,实现“密码错误3次封IP”的需求
服务器·tcp/ip·安全
unfeeling_7 天前
Keepalived实验
linux·服务器·网络