项目场景:
设计一个socket server端传输数据,在server传输线程中设计两个server socket套接字。
主要是想阐述为什么设计两个socket server,设计两个socket server的目的。
设计目的与意义:
一个server端是现实和外部的建立socket 通信连接,一个server端实现对相应端口进行数据传输。
代码如下:
ServerSocket server (m_port, m_pipefds[0]);
ServerSocket new_sock(m_pipefds[0]);
int rc = server.accept(new_sock, pipeflag, m_client_connected);
Socket::accept(sock)
sock.SetupEpoll(m_pipefd);
设计详解:
在其中有两个类,Socket class 和公有继承的ServerSocket class,在Socket class中有着最基本的listen、accept之类的函数,
ServerSocket 公有继承之后扩展出对epoll_event event进行注册加入epoll监听的功能。在其中两种数据来源,一种是socket消息,一种是pipe消息。
代码如下:
bool Socket::listen() const
{
if (!is_valid()) {
return false;
}
//m_sock为建立的listening socket
int listen_return = ::listen(m_sock, MAXCONNECTIONS);
if (listen_return == -1) {
return false;
}
return true;
}
bool Socket::accept(Socket &new_socket) const
{
int addr_length = sizeof(m_addr);
//accept通过m_sock建立new_socket类成员m_sock为 connected descriptor,真正与外部通信的socket
new_socket.m_sock = ::accept(m_sock, (sockaddr *) &m_addr, (socklen_t *) &addr_length);
if (new_socket.m_sock <= 0) {
LOGE("Socket accept error: %s, errno:%d", strerror(errno), errno);
return false;
}
return true;
}
ServerSocket::ServerSocket(unsigned short port, int pipefd){
bool rc = Socket::create();
if (port) {
rc = Socket::bind(port);}
rc = Socket::listen();
if (pipefd >= 0) {
SetupEpoll(pipefd);}
}
bool Socket::accept(Socket &new_socket) const
{
int addr_length = sizeof(m_addr);
new_socket.m_sock = ::accept(m_sock, (sockaddr *) &m_addr, (socklen_t *) &addr_length);
if (new_socket.m_sock <= 0) {
return false;}
return true;
}
void ServerSocket::SetupEpoll(int pipefd)
{
m_pipefd = pipefd;
Socket::set_non_blocking(true);
if(m_efd != -1) {
::close(m_efd);
}
m_efd = epoll_create(sizeof(epoll_event));
struct epoll_event event;
event.data.fd = m_sock;
event.events = EPOLLIN;
epoll_ctl(m_efd, EPOLL_CTL_ADD, m_sock, &event);
event.data.fd = m_pipefd;
event.events = EPOLLIN;
epoll_ctl(m_efd, EPOLL_CTL_ADD, m_pipefd, &event);
}