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缓冲区
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;
//可读事件
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;
//绑定TCP端口
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 ) );
//绑定UDP端口
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 );
//TCP端口注册事件
addfd( epollfd, udpfd );
//UDP端口注册事件
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++ )
//EPOLL就绪事件
{
int
sockfd = events[i].data.fd;
if
( sockfd == listenfd )
//监听端口监听TCP连接事件
{
struct
sockaddr_in client_address;
socklen_t client_addrlength =
sizeof
( client_address );
int
connfd = accept( listenfd, (
struct
sockaddr* )&client_address, &client_addrlength );
addfd( epollfd, connfd );
}
else
if
( sockfd == udpfd )
//UDP连接
{
char
buf[ UDP_BUFFER_SIZE ];
memset
( buf,
'\0'
, UDP_BUFFER_SIZE );
struct
sockaddr_in client_address;
socklen_t client_addrlength =
sizeof
( client_address );
//客户端地址
//UDP专用接收数据
ret = recvfrom( udpfd, buf, UDP_BUFFER_SIZE-1, 0, (
struct
sockaddr* )&client_address, &client_addrlength );
if
( ret > 0 )
{
//UDP专用发送数据(回射数据)
sendto( udpfd, buf, UDP_BUFFER_SIZE-1, 0, (
struct
sockaddr* )&client_address, client_addrlength );
}
}
else
if
( events[i].events & EPOLLIN )
//TCP连接
{
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
( (
errno
== EAGAIN ) || (
errno
== EWOULDBLOCK ) )
//非阻塞出现这种errrno是读取数据完毕
{
break
;
}
close( sockfd );
break
;
}
else
if
( ret == 0 )
//关闭连接
{
close( sockfd );
}
else
{
send( sockfd, buf, ret, 0 );
//回射数据
}
}
}
else
{
printf
(
"something else happened \n"
);
}
}
}
close( listenfd );
return
0;
}
客户端程序:
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
using
namespace
std;
int
main(
int
argc,
char
* argv[]){
if
(argc<=2){
cout<<
"argc<=2"
<<endl;
return
1;
}
const
char
* ip=argv[1];
int
port=
atoi
(argv[2]);
struct
sockaddr_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);
int
sockfd=socket(PF_INET,SOCK_STREAM,0);
int
sockudp=socket(PF_INET,SOCK_DGRAM,0);
assert
(sockfd>=0);
if
(connect(sockfd,(
struct
sockaddr*)&server_address,
sizeof
(server_address))<0){
//TCP数据发送与接收
cout<<
"connect error"
<<endl;
return
1;
}
else
{
const
char
* tcp=
"this is TCP data\n"
;
send(sockfd,tcp,
strlen
(tcp),0);
char
buf[BUF_SIZE];
int
ret=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,(
struct
sockaddr*)&server_address,
sizeof
(server_address))<0){
//UDP数据发送与接收
cout<<
"connect error"
<<endl;
return
1;
}
else
{
const
char
* udp=
"this is UDP data\n"
;
send(sockudp,udp,
strlen
(udp),0);
char
buf[BUF_SIZE];
int
ret=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);
return
0;
}
0 0
- IO复用高级应用:同时处理TCP和UDP服务
- IO复用高级应用:同时处理TCP和UDP服务
- IO复用的高级应用:同时处理TCP和UDP的服务
- I/O复用的高级应用三:同时处理TCP和UDP服务
- linux网络编程十七:I/O复用的应用-同时处理TCP和UDP服务
- epoll高级应用之同时处理 tcp/udp 的服务器
- Linux网络编程--使用epoll模型同时处理tcp和udp服务
- Linux网络编程--使用epoll模型同时处理tcp和udp服务
- linux C++ 同时监听多个端口 同时处理TCP和UDP服务请求的回射服务器
- 一台电脑的一个网口同时支持TCP和UDP服务
- DNS同时使用TCP和UDP?
- Linux下使用epoll函数同时处理TCP请求和UDP请求的回射服务器
- linux高性能服务器编程之同时处理UDP请求和TCP请求的服务器
- 高级IO复用应用:聊天室程序
- 高级IO复用应用:聊天室程序
- TCP和UDP的区别和应用
- 集中管理器如何同时接收tcp和UDP信息
- 同时使用tcp和udp回射服务器
- Java web----POST和GET中文编码问题
- Lucence入门实例
- ural 1073. Square Country 完全背包
- hibernate基于连接表的多对一单向关联
- hibernate4通过注解方式整合sessionFactory策略
- IO复用高级应用:同时处理TCP和UDP服务
- 2015 坚持
- 自定义组件<五>
- git merge commitId 把其他分支的某次提交merge进该分支
- Unrecognized Windows Sockets error 0 JVM_Bind异常解决办法
- 备查ant配置发送邮件
- IIS7.5+Mysql5.6.22+PHP5.6.4安装配置
- 【难】【BET】无重复值的搜索二叉树的插入和删除操作
- unexpected T_ENDFOREACH PHP FOREACH循环 syntax error, unexpected T_ENDFOREACH错误