linux高性能服务器编程之同时处理UDP请求和TCP请求的服务器

源代码如下:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <pthread.h>

/*宏定义区*/
#define     MAX_EVENT_NUMBER        1024
#define     TCP_BUFFER_SIZE         1024
#define     UDP_BUFFER_SIZE         1024

/*函数声明*/
int setnonblocking(int fd);


int setnonblocking(int fd)
{
    int old_option = fcntl(fd,F_GETFL);
    int new_option = old_option | O_NONBLOCK;
    fcntl(fd,F_SETFL,new_option);
    return old_option;
}

int reuse_address(int fd)
{
    int option = 1;
    int nRes = setsockopt(fd,SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
    if(nRes < 0)
    {
        return 0;
    }
    return 1;
}

void addfd(int epollfd,int fd,bool enable_et)
{
    epoll_event event;
    event.data.fd = fd;
    event.events = EPOLLIN;

    if(enable_et)
    {
        event.events |= EPOLLET;
    }

    epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&event);
    setnonblocking(fd);
}

int main(int argc,char* argv[])
{
    if(argc <=2)
    {
        printf("usage:ddddd");
        return 1;
    }

    const char* ip = argv[1];
    int port = atoi(argv[2]);

    int ret = 0;
    struct sockaddr_in address;
    bzero(&address,sizeof(address));
    address.sin_family = AF_INET;
    inet_pton(AF_INET,ip,&address.sin_addr);
    address.sin_port = htons(port);

    /*创建tcp socket,并将其绑定到端口上*/
    int listenfd = socket(AF_INET,SOCK_STREAM,0);
    assert(listenfd >=0);

    reuse_address(listenfd);

    ret = bind(listenfd,(struct sockaddr*)&address,sizeof(address));
    assert(ret != -1);

    ret = listen(listenfd,5);
    assert(ret!=-1);

    //创建udp套接字
    bzero(&address,sizeof(address));
    address.sin_family = AF_INET;
    inet_pton(AF_INET,ip,&address.sin_addr);
    address.sin_port = htons(port);
    int udpfd = socket(AF_INET,SOCK_DGRAM,0);
    assert(udpfd >= 0);

    //绑定udp套接字
    ret = bind(udpfd,(struct sockaddr*)&address,sizeof(address));
    assert(ret != -1);

    epoll_event events[MAX_EVENT_NUMBER];
    int epollfd = epoll_create(5);
    assert(epollfd!=-1);

    /*注册tcp 和 udp socket上的可读事件*/
    addfd(epollfd,listenfd,true);
    addfd(epollfd,udpfd,true);

    while(1)
    {
        int ret = epoll_wait(epollfd,events,MAX_EVENT_NUMBER,-1);
        //判断返回值
        if(ret < 0)
        {
            printf("epoll failure!");
            break;
        }
        for(int i = 0;i<ret;i++)
        {
            int sockfd = events[i].data.fd;
            if(sockfd == listenfd)
            {
                struct sockaddr_in client_address;
                socklen_t client_addrlen = sizeof(client_address);

                int connfd = accept(listenfd,(struct sockaddr*)&client_address,&client_addrlen);

                /*侦听非侦听socket都注册EPOLLONESHOT事件*/
                addfd(epollfd,connfd,true);
            }
            else if(sockfd == udpfd)
            {
                char buf[UDP_BUFFER_SIZE];
                memset(buf,0,UDP_BUFFER_SIZE);

                struct sockaddr_in client_address;
                socklen_t client_addrlength = sizeof(client_address);

                ret = recvfrom(udpfd,buf,UDP_BUFFER_SIZE-1,0,
                                (struct sockaddr*)&client_address,&client_addrlength);

                if(ret > 0)
                {
                    //sendto(udpfd,buf,UDP_BUFFER_SIZE-1,0,(struct sockaddr*)&client_address,client_addrlength);
                    printf("udp recv content is %s\r\n",buf);
                }
            }
            else if(events[i].events & EPOLLIN)
            {
                char buf[TCP_BUFFER_SIZE];
                while(1)
                {
                    memset(buf,0,TCP_BUFFER_SIZE);
                    //接收数据
                    ret = recv(sockfd,buf,TCP_BUFFER_SIZE-1,0);
                    if(ret < 0)
                    {
                        if(EAGAIN == errno || EWOULDBLOCK == errno)
                        {
                            break;
                        }
                        close(sockfd);
                        break;
                    }
                    else if(ret == 0)
                    {
                        close(sockfd);
                    }
                    else
                    {
                        //send(sockfd,buf,ret,0);
                        //输出内容
                        printf("tcp recv content is %s\r\n",buf);
                    }
                }
            }
            else
            {
                //printf("something else happened!\r\n");
            }
        }

    }

    close(listenfd);
    return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值