IO复用高级应用:同时处理TCP和UDP服务

来源:互联网 发布:蜗牛移动 网络 编辑:程序博客网 时间:2024/05/16 15:31
一个socket只能与一个socket地址绑定即一个socket只能监听一个端口,服务器如果要同时监听多个端口就必须创建多个socket,若在同一个端口监听多个服务也要创建多个socket绑定到这个端口上。现在服务器监听一个端口上的TCP和UDP请求,并将发送来的数据回射到客户端。
服务端程序:
 
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#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//TCP缓冲区 
#define UDP_BUFFER_SIZE 1024//UDP缓冲区 
   
intsetnonblocking( intfd )//设置为非阻塞描述符 
    intold_option = fcntl( fd, F_GETFL ); 
    intnew_option = old_option | O_NONBLOCK; 
    fcntl( fd, F_SETFL, new_option ); 
    returnold_option; 
   
voidaddfd( intepollfd, intfd )//注册事件 
    epoll_event event; 
    event.data.fd = fd; 
    //event.events = EPOLLIN | EPOLLET; 
    event.events = EPOLLIN;//可读事件 
    epoll_ctl( epollfd, EPOLL_CTL_ADD, fd, &event ); 
    setnonblocking( fd ); 
   
intmain( intargc, char* argv[] ) 
    if( argc <= 2 ) 
    
        printf("usage: %s ip_address port_number\n", basename( argv[0] ) ); 
        return1; 
    
    constchar* ip = argv[1]; 
    intport = atoi( argv[2] ); 
   
    intret = 0; 
    structsockaddr_in address;//绑定TCP端口 
    bzero( &address, sizeof( address ) ); 
    address.sin_family = AF_INET; 
    inet_pton( AF_INET, ip, &address.sin_addr ); 
    address.sin_port = htons( port ); 
   
    intlistenfd = socket( PF_INET, SOCK_STREAM, 0 ); 
    assert( listenfd >= 0 ); 
   
    ret = bind( listenfd, ( structsockaddr* )&address, sizeof( address ) ); 
    assert( ret != -1 ); 
   
    ret = listen( listenfd, 5 ); 
    assert( ret != -1 ); 
   
    bzero( &address, sizeof( address ) );//绑定UDP端口 
    address.sin_family = AF_INET; 
    inet_pton( AF_INET, ip, &address.sin_addr ); 
    address.sin_port = htons( port ); 
    intudpfd = socket( PF_INET, SOCK_DGRAM, 0 ); 
    assert( udpfd >= 0 ); 
   
    ret = bind( udpfd, ( structsockaddr* )&address, sizeof( address ) ); 
    assert( ret != -1 ); 
   
    epoll_event events[ MAX_EVENT_NUMBER ]; 
    intepollfd = epoll_create( 5 ); 
    assert( epollfd != -1 ); 
    addfd( epollfd, listenfd );//TCP端口注册事件 
    addfd( epollfd, udpfd );//UDP端口注册事件 
   
    while( 1 ) 
    
        intnumber = epoll_wait( epollfd, events, MAX_EVENT_NUMBER, -1 );//无限期等待事件发生 
        if( number < 0 ) 
        
            printf("epoll failure\n" ); 
            break
        
       
        for( inti = 0; i < number; i++ )//EPOLL就绪事件 
        
            intsockfd = events[i].data.fd; 
            if( sockfd == listenfd )//监听端口监听TCP连接事件 
            
                structsockaddr_in client_address; 
                socklen_t client_addrlength = sizeof( client_address ); 
                intconnfd = accept( listenfd, ( structsockaddr* )&client_address, &client_addrlength ); 
                addfd( epollfd, connfd ); 
            
            elseif ( sockfd == udpfd )//UDP连接 
            
                charbuf[ UDP_BUFFER_SIZE ]; 
                memset( buf, '\0', UDP_BUFFER_SIZE ); 
                structsockaddr_in client_address; 
                socklen_t client_addrlength = sizeof( client_address );//客户端地址 
        //UDP专用接收数据 
                ret = recvfrom( udpfd, buf, UDP_BUFFER_SIZE-1, 0, ( structsockaddr* )&client_address, &client_addrlength ); 
                if( ret > 0 ) 
                {//UDP专用发送数据(回射数据) 
                    sendto( udpfd, buf, UDP_BUFFER_SIZE-1, 0, ( structsockaddr* )&client_address, client_addrlength ); 
                
            
            elseif ( events[i].events & EPOLLIN )//TCP连接 
            
                charbuf[ TCP_BUFFER_SIZE ]; 
                while( 1 ) 
                
                    memset( buf, '\0', TCP_BUFFER_SIZE ); 
                    ret = recv( sockfd, buf, TCP_BUFFER_SIZE-1, 0 ); 
                    if( ret < 0 ) 
                    
                        if( ( errno== EAGAIN ) || ( errno== EWOULDBLOCK ) )//非阻塞出现这种errrno是读取数据完毕 
                        
                            break
                        
                        close( sockfd ); 
                        break
                    
                    elseif( ret == 0 )//关闭连接 
                    
                        close( sockfd ); 
                    
                    else 
                    
                        send( sockfd, buf, ret, 0 );//回射数据 
                    
                
            
            else 
            
                printf("something else happened \n" ); 
            
        
    
   
    close( listenfd ); 
    return0; 
}

 

 
客户端程序:
 
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include<sys/socket.h> 
#include<netinet/in.h> 
#include<arpa/inet.h> 
#include<assert.h> 
#include<stdio.h> 
#include<unistd.h> 
#include<string.h> 
#include<stdlib.h> 
#include<iostream> 
#define BUF_SIZE 1024 
usingnamespace std; 
intmain(intargc,char* argv[]){ 
    if(argc<=2){ 
        cout<<"argc<=2"<<endl; 
        return1; 
    
    constchar* ip=argv[1]; 
    intport=atoi(argv[2]); 
    structsockaddr_in server_address; 
    bzero(&server_address,sizeof(server_address)); 
    server_address.sin_family=AF_INET; 
    inet_pton(AF_INET,ip,&server_address.sin_addr); 
    server_address.sin_port=htons(port); 
    intsockfd=socket(PF_INET,SOCK_STREAM,0); 
    intsockudp=socket(PF_INET,SOCK_DGRAM,0); 
    assert(sockfd>=0); 
    if(connect(sockfd,(structsockaddr*)&server_address,sizeof(server_address))<0){//TCP数据发送与接收 
        cout<<"connect error"<<endl; 
        return1; 
    
    else
        constchar* tcp="this is TCP data\n"
        send(sockfd,tcp,strlen(tcp),0); 
        charbuf[BUF_SIZE]; 
        intret=recv(sockfd,buf,BUF_SIZE-1,0); 
        if(ret<0){ 
            cout<<"recv tcp error"<<endl; 
        
        else
            buf[ret+1]='\0'
            cout<<ret<<" "<<buf<<endl; 
        
    
    if(connect(sockudp,(structsockaddr*)&server_address,sizeof(server_address))<0){//UDP数据发送与接收
        cout<<"connect error"<<endl; 
        return1; 
    
    else
        constchar* udp="this is UDP data\n"
        send(sockudp,udp,strlen(udp),0); 
        charbuf[BUF_SIZE]; 
        intret=recv(sockudp,buf,BUF_SIZE-1,0); 
        if(ret<0){ 
            cout<<"recv udp error"<<endl; 
        
        else
            buf[ret+1]='\0'
            cout<<ret<<" "<<buf<<endl; 
        
    
    close(sockfd); 
    return0; 
0 0
原创粉丝点击