目录
Poll系统调用poll编程实例poll编程流程头文件tcp_socket.h头文件tcp_poll.h主文件tcp_poll.cpp
参考文献
Poll系统调用
poll系统调用和select类似,也是在指定时间内轮询一定数量的文件描述符,以 测试其是否有就绪者。
#include <poll.h>
int poll(struct pollfd
* fds
, nfds_t nfds
, int timeout
);
struct pollfd
{
int fd
;
short events
;
short revents
;
};
fds参数是一个pollfd类型的数组,它指定所有我们感兴趣的文件描述符上发生的可读、可写和异常等事件。 其中fd成员指定文件描述符;events成员告诉poll监听fd上的哪些事件,它是一系列事件的按位或;revents成员则由内核修改,以通知应用程序fd上实际发生了哪些事件。poll事件类型 nfds参数指定了被监听事件集合fds的大小。
typedef unsigned long int nfds_t
;
timeout则指定poll的超时值
poll编程实例
poll编程流程
头文件tcp_socket.h
#include<iostream>
#include<assert.h>
#include<string.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<unistd.h>
#define BUFF_SIZE 128
using namespace std
;
class Socket
{
public:
Socket()
{
sockfd_
= socket(PF_INET
, SOCK_STREAM
, 0);
assert(sockfd_
>= 0);
}
int Get_socket()
{
return sockfd_
;
}
~Socket()
{
close(sockfd_
);
}
protected:
int sockfd_
;
};
class Socket_Ser :public Socket
{
public:
Socket_Ser(const char* ip
, int port
= 6000, int backlog
= 5)
{
struct sockaddr_in address
;
memset(&address
, 0, sizeof(address
));
address
.sin_family
= AF_INET
;
address
.sin_port
= htons(port
);
address
.sin_addr
.s_addr
= inet_addr(ip
);
int ret
= bind(sockfd_
, (struct sockaddr
*)&address
, sizeof(address
));
assert(ret
!= -1);
ret
= listen(sockfd_
, backlog
);
assert(ret
!= -1);
}
int Accept()
{
struct sockaddr_in client
;
socklen_t len
= sizeof(client
);
int connfd
= accept(sockfd_
, (struct sockaddr
*)&client
, &len
);
return connfd
;
}
int Recv(int fd
, char* buffer
, int size
)
{
int ret
= recv(fd
, buffer
, size
- 1, 0);
if (ret
== -1 || (strncmp(buffer
, "end", 3) == 0))
{
return -1;
}
}
void Send(int fd
, const char* buffer
, int size
)
{
send(fd
, buffer
, size
, 0);
}
void Close_client(int fd
)
{
close(fd
);
}
};
class Socket_Cli :public Socket
{
public:
Socket_Cli(const char* ip
, int port
= 6000)
{
struct sockaddr_in address
;
memset(&address
, 0, sizeof(address
));
address
.sin_family
= AF_INET
;
address
.sin_port
= htons(port
);
address
.sin_addr
.s_addr
= inet_addr(ip
);
int ret
= connect(sockfd_
, (struct sockaddr
*)&address
, sizeof(address
));
assert(ret
!= -1);
}
int Send(char* buffer
, int size
)
{
send(sockfd_
, buffer
, size
, 0);
}
};
头文件tcp_poll.h
#include"tcp_socket.h"
#include <poll.h>
#include <list>
#define PollSize 100
class Poll
{
public:
Poll(const char* ip
, int port
= 6000, int backlog
= 5) :ser(ip
, port
, backlog
)
{
for (int i
= 0; i
< PollSize
; i
++)
{
cli_arr
[i
].fd
= -1;
cli_arr
[i
].events
= 0;
}
Insert(ser
.Get_socket(), POLLIN
);
}
public:
void Deal()
{
UsingPoll();
Deal_connect();
}
private:
void Insert(int fd
, short events
)
{
int i
= 0;
for (; i
< PollSize
; i
++)
{
if (cli_arr
[i
].fd
== -1)
{
cli_arr
[i
].fd
= fd
;
cli_arr
[i
].events
= events
;
break;
}
}
if (i
== PollSize
) cout
<< "client array is full!" << endl
;
}
void Delete(struct pollfd
& PollFd
)
{
ser
.Close_client(PollFd
.fd
);
PollFd
.fd
= -1;
PollFd
.events
= 0;
}
void Deal_connect()
{
for (int i
= 0; i
< PollSize
; i
++)
{
if (cli_arr
[i
].fd
== ser
.Get_socket())
{
if (cli_arr
[i
].revents
& POLLIN
)
{
int connfd
= ser
.Accept();
cout
<< "client " << connfd
<< "link" << endl
;
Insert(connfd
, POLLIN
| POLLRDHUP
);
}
}
else
{
if (cli_arr
[i
].revents
& POLLRDHUP
)
{
cout
<< "client " << cli_arr
[i
].fd
<< "unlink" << endl
;
Delete(cli_arr
[i
]);
}
else if (cli_arr
[i
].revents
& POLLIN
)
{
char buffer
[128] = { 0 };
ser
.Recv(cli_arr
[i
].fd
, buffer
, 128);
cout
<< "recv form " << cli_arr
[i
].fd
<< ":" << buffer
<< endl
;
}
}
}
}
int UsingPoll()
{
int n
= poll(cli_arr
, PollSize
, -1);
if (n
<= 0)
{
cout
<< "poll error" << endl
;
return -1;
}
}
private:
Socket_Ser ser
;
struct pollfd cli_arr
[PollSize
];
};
主文件tcp_poll.cpp
#include "tcp_poll.h"
int main(int argc
, char* argv
[])
{
if (argc
<= 1)
{
cout
<< "errno! please input again" << endl
;
}
Poll
mypoll(argv
[1]);
while (1)
{
mypoll
.Deal();
}
}
参考文献
[1]游双.Linux高性能服务器编程.机械工业出版社,2043.5.