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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值