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