linux socket TCP UDP bind 同义IP和port-程序员宅基地

技术标签: 网络  epoll  

//TCP and UDP can bind to the same IP & port.

#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 512
#define UDP_BUFFER_SIZE 1024

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;
}

void addfd( int epollfd, int fd )
{
    epoll_event event;
    event.data.fd = fd;
    //event.events = EPOLLIN | EPOLLET;
    event.events = EPOLLIN; //concern about read event
    epoll_ctl( epollfd, EPOLL_CTL_ADD, fd, &event );
    setnonblocking( fd );
}

int main( int argc, char* argv[] )
{
    if( argc <= 2 )
    {
        printf( "usage: %s ip_address port_number\n", basename( argv[0] ) );
        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 );

    int listenfd = socket( PF_INET, SOCK_STREAM, 0 );
    assert( listenfd >= 0 );

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

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

    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( PF_INET, SOCK_DGRAM, 0 );
    assert( udpfd >= 0 );

    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 );
    addfd( epollfd, listenfd );
    addfd( epollfd, udpfd );

    while( 1 )
    {
        int number = epoll_wait( epollfd, events, MAX_EVENT_NUMBER, -1 );
        if ( number < 0 )
        {
            printf( "epoll failure\n" );
            break;
        }
    
        for ( int i = 0; i < number; i++ )
        {
            int sockfd = events[i].data.fd;
            if ( sockfd == listenfd )
            {
                struct sockaddr_in client_address;
                socklen_t client_addrlength = sizeof( client_address );
                int connfd = accept( listenfd, ( struct sockaddr* )&client_address, &client_addrlength );
                if ( connfd < 0 )
    			{
        			printf( "errno is: %d\n", errno );
    			}
    			else
    			{
    				addfd( epollfd, connfd );
                	char remote[INET_ADDRSTRLEN ];
        			printf( "connected client ip: %s and port: %d\n", 
            			inet_ntop( AF_INET, &client_address.sin_addr, remote, INET_ADDRSTRLEN ), ntohs( client_address.sin_port ) );
    			}
            }
            //UDP is readable
            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 );
                }
                else if (ret == 0)
                {
                	printf("client peer closed().\n");
                	//shutdown(udpfd);   //udp套接字而言shutdown毫无意义
                	close(udpfd);
                }
                else
                {
                	printf("UDP recvfrom ran into error: \n", errno);
                	//handle error....
                }
            }
            //TCP connfd is readable
            else if ( events[i].events & EPOLLIN )
            {
                char buf[ TCP_BUFFER_SIZE ];
                while( 1 )
                {
                    memset( buf, '\0', TCP_BUFFER_SIZE );
                    //sockfd is nonblock
                    ret = recv( sockfd, buf, TCP_BUFFER_SIZE-1, 0 );
                    if( ret < 0 )
                    {
                        if( ( errno == EAGAIN ) || ( errno == EWOULDBLOCK ) || (errno == EINTR) )
                        {
                            break;
                        }
                        else
                        {
                        	printf("TCP recv ran into error, close() socket.\n");
                        	close( sockfd );
                        	break;
                        }
                    }
                    else if( ret == 0 ) //peer called close() and sent a FIN to here
                    {
                    	printf("TCP recv return 0: peer client close(), so close() self.\n");
                        close( sockfd );
                    }
                    else  //normal, send back what we have received! ECHO~
                    {
                        send( sockfd, buf, ret, 0 );
                    }
                }
            }
            else
            {
                printf( "something else happened \n" );
            }
        }
    }

    close( listenfd );
    return 0;
}

  

转载于:https://www.cnblogs.com/kex1n/p/7461216.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/diaoqu4574/article/details/102222865

智能推荐

python宝典 宋强 pdf_Python宝典/宝典丛书:杨佩璐//宋强 : 电子电脑 :计算机技术 :程序与语言 ...-程序员宅基地

文章浏览阅读279次。导语《Python宝典》由杨佩璐、宋强等编著,本书内容共分三篇26章,分别为入门篇、高级篇和案例篇,针对Python的常用扩展模块给出了详细的语法介绍,并且给出了典型案例,通过对本书的学习,读者能够很快地使用Python进行编程开发。本书以PVthon 3.x为基础进行讲解,并在与Python 2.x有区别的地方加上了相关介绍,使Pvthon 2.x和Pvthon 3.x的读者都能使用本书。内容提..._python宝典杨佩璐

js对象遍历输出的时候真的是按照顺序输出吗?_map循环遍历对象数据是顺序的吗-程序员宅基地

文章浏览阅读1.3w次。js对象遍历输出的时候真的是按照顺序输出吗?  下边就来实践一下:var obj={'3':'ccc',name:'abc',age:23,school:'sdfds',class:'dfd',hobby:'dsfd'};Object.keys(obj)输出:["3", "name", "age", "school", "class", "hobby"];换一下对象顺序,var obj=_map循环遍历对象数据是顺序的吗

HDU--4305(生成树计数)-程序员宅基地

文章浏览阅读176次。2015-09-0722:23:26【传送门】题意:平面上300个点,如果两点之间距离<=R,且两点形成的线段上没有另外的点,那么两点之间有一条无向边。问生成树的方案数。思路:暴力n^2建图,关于判断两点形成线段上是否有其他点,比如判断 k 点知否在 i ,j 之间,首先看斜率是否相等,不能直接求斜率,而应该转化为乘式;再判断 dis(i,k)+dis(k,j)是否等..._hdu4305

阿里云OSS请求文件跨域问题Access-Control-Allow-Origin_oss预签名url access-control-allow-origin-程序员宅基地

文章浏览阅读2.2k次。跨域问题网上很多解决方案提示到这里配置但是不生效,一定要勾选Vary:Origin这个选项,请求的时候浏览器记得请求在控制台要清理缓存。_oss预签名url access-control-allow-origin

OpenCV - C++ - cv::setWindowProperty-程序员宅基地

文章浏览阅读4k次,点赞2次,收藏2次。OpenCV - C++ - cv::setWindowPropertyHigh-level GUI#include <opencv2/highgui.hpp>1. setWindowProperty()void cv::setWindowProperty(const String &winname, int prop_id, double prop_value) - C++None = cv.setWindowProperty(winname, prop_id, prop__setwindowproperty

Qt Creator 4.13中的CMake项目配置_qt cmake configuration-程序员宅基地

文章浏览阅读5.1k次,点赞3次,收藏4次。在Qt Creator中配置中型到大型CMake项目可能是一个挑战。这是因为您需要给CMake传递正确配置项目的选项太多了。让我们以Qt Creator的CMake为例。不同于qmake构建,CMake构建可配置你想要构建的插件。_qt cmake configuration

随便推点

AMOS分析技术:二阶验证性因子分析-程序员宅基地

文章浏览阅读4.8w次,点赞5次,收藏90次。基础准备草堂君在前面介绍了验证性因子分析的内容,包括验证性因子分析与探索性因子分析的区别联系,斜交验证性因子分析和正交验证性因子分析,可以点击下方文章链接回顾:AMOS分析技术:验证性因子分析介绍;信度与效度指标详解AMOS分析技术:斜交验证性因子分析;介绍如何整理出能够放入论文的模型信效度结果AMOS分析技术:正交验证性因子分析;模型拟合质量好,模型就一定好吗?今天草堂君要介绍的是二阶验证性因子_二阶验证性因子分析

读jQuery之二十(Deferred对象)-程序员宅基地

文章浏览阅读55次。为什么80%的码农都做不了架构师?>>> ...

C++代码实现Top-K问题最优解决办法_c++用优先队列解决topk-程序员宅基地

文章浏览阅读1.6k次。Top-K问题Top-K问题1、问题描述2、解法思想和实现Top-K问题1、问题描述Top-K问题是一个十分经典的问题,一般有以下两种方式来描述问题:在10亿的数字里,找出其中最大的100个数;或者在一个包含n个整数的数组中,找出最大的100个数。前边两种问题描述稍有区别,但都是说的Top-K问题,前一种描述方式是说这里也许没有足够的空间存储大量的数字或其他东西,我们最好可以在一边输入数据,一边求出结果,而不需要存储数据;后一种说法则表示可以存储数据,这种情况下,最简单直观的想法就是对数组进行排序,_c++用优先队列解决topk

怎么用matlab剔除数据的异常值(3σ准则)_3sigma原则matlab-程序员宅基地

文章浏览阅读5.2w次,点赞27次,收藏379次。参考:https://blog.csdn.net/weixin_30633405/article/details/951770093σ准则又称为拉依达准则,它是先假设一组检测数据只含有随机误差,对其进行计算处理得到标准偏差,按一定概率确定一个区间,认为凡超过这个区间的误差,就不属于随机误差而是粗大误差,含有该误差的数据应予以剔除。且3σ适用于有较多组数据的时候。这种判别处理原理及方法仅局限于对正态或近似正态分布的样本数据处理,它是以测量次数充分大为前提的,当测量次数较少的情形用准则剔除粗大误_3sigma原则matlab

导入PYQT5不能使用的坑_pdroid3已经导入pyqt5怎么不管用-程序员宅基地

文章浏览阅读5.1k次,点赞4次,收藏17次。如图:import进来之后里面的类全都不能用是因为这个引用路径下面有中文。改成英文的就不报错了,如果还是报错,那就新建一个项目命名成英文_pdroid3已经导入pyqt5怎么不管用

手推线性模型及最小二乘法(房价预测实例)_基于最小二乘法的房价预测实验报告-程序员宅基地

文章浏览阅读1.4k次,点赞4次,收藏24次。手推线性模型及最小二乘法(房价预测实例)线性模型及最小二乘法推导房价预测实例Reference线性模型及最小二乘法推导房价预测实例生成数据#生成数据import numpy as np#生成随机数np.random.seed(1234)x = np.random.rand(500,3)#构建映射关系,模拟真实的数据待预测值,映射关系为y = 4.2 + 5.7*x1 + 1..._基于最小二乘法的房价预测实验报告

推荐文章

热门文章

相关标签