二、对Socket的封装
Socket的调用主要包含以下的步骤:
调用比较复杂,我们首先区分两类Socket,一类是Listening Socket,一类是Connected Socket.
Listening Socket由MySocketServer负责,一旦accept,则生成一个Connected Socket,又MySocket负责。
MySocket主要实现的方法如下:
int MySocket::write(const char * buf, int length)
{
int ret = 0;
int left = length;
int index = 0;
while(left > 0)
{
ret = send(m_socket, buf + index, left, 0);
if(ret == 0)
break;
else if(ret == -1)
{
break;
}
left -= ret;
index += ret;
}
if(left > 0)
return -1;
return 0;
}
int MySocket::read(char * buf, int length)
{
int ret = 0;
int left = length;
int index = 0;
while(left > 0)
{
ret = recv(m_socket, buf + index, left, 0);
if(ret == 0)
break;
else if(ret == -1)
return -1;
left -= ret;
index += ret;
}
return index;
}
int MySocket::status()
{
int status;
int ret;
fd_set checkset;
struct timeval timeout;
FD_ZERO(&checkset);
FD_SET(m_socket, &checkset);
timeout.tv_sec = 10;
timeout.tv_usec = 0;
status = select((int)m_socket + 1, &checkset, 0, 0, &timeout);
if(status < 0)
ret = -1;
else if(status == 0)
ret = 0;
else
ret = 0;
return ret;
}
int MySocket::close()
{
struct linger lin;
lin.l_onoff = 1;
lin.l_linger = 0;
setsockopt(m_socket, SOL_SOCKET, SO_LINGER, (const char *)&lin, sizeof(lin));
::close(m_socket);
return 0;
}
MySocketServer的主要方法实现如下:
int MySocketServer::init(int port)
{
if((m_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
return -1;
}
struct sockaddr_in serverAddr;
memset(&serverAddr, 0, sizeof(struct sockaddr_in));
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(port);
if(bind(m_socket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == -1)
{
::close(m_socket);
return -1;
}
if(listen(m_socket, SOMAXCONN) == -1)
{
::close(m_socket);
return -1;
}
struct linger lin;
lin.l_onoff = 1;
lin.l_linger = 0;
setsockopt(m_socket, SOL_SOCKET, SO_LINGER, (const char *)&lin, sizeof(lin));
m_port = port;
m_inited = true;
return 0;
}
MySocket * MySocketServer::accept()
{
int sock;
struct sockaddr_in clientAddr;
socklen_t clientAddrSize = sizeof(clientAddr);
if((sock = ::accept(m_socket, (struct sockaddr *)&clientAddr, &clientAddrSize)) == -1)
{
return NULL;
}
MySocket* socket = new MySocket(sock);
return socket;
}
MySocket * MySocketServer::accept(int timeout)
{
struct timeval timeout;
timeout.tv_sec = timeout;
timeout.tv_usec = 0;
fd_set checkset;
FD_ZERO(&checkset);
FD_SET(m_socket, &checkset);
int status = (int)select((int)(m_socket + 1), &checkset, NULL, NULL, &timeout);
if(status < 0)
return NULL;
else if(status == 0)
return NULL;
if(FD_ISSET(m_socket, &checkset))
{
return accept();
}
}
本文导航
- 第1页: 首页
- 第2页: 对Socket的封装
- 第3页: 线程池的实现
- 第4页: 连接池的实现
- 第5页: 监听线程的实现