1、在reactor框架下加入tcp
Unix下的tcp连接也是经由socket文件描述符(sockfd)实现的。此节只是封装了listening sockefd进行监听(accept(2)),得到的新连接(普通sockfd)直接提供给用户让用户自行处理。下一节才进一步地将得到的新连接也封装起来。
1.1、首先将unix下的socket调用api简易封装成Socket类,得到wapper。即将api调用如socket()、bind()、listen()、accept()等裹上对错误返回值的处理。
#ifndef SOCKET_H_
#define SOCKET_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
class Socket
{
public:
Socket(unsigned short port) : port_(port)
{
sockfd_ = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd_<0)
{
perror("socket");
exit(-1);
}
// non-block
int flags = ::fcntl(sockfd_, F_GETFL, 0);
flags |= O_NONBLOCK;
int ret = ::fcntl(sockfd_, F_SETFL, flags);
if(ret==-1)
{
perror("fcntl");
exit(-1);
}
// close-on-exec
flags = ::fcntl(sockfd_, F_GETFD, 0);
flags |= FD_CLOEXEC;
ret = ::fcntl(sockfd_, F_SETFD, flags);
if(ret==-1)
{
perror("fcntl");
exit(-1);
}
}
void setReuseAddr(bool on)
{
int optval = on ? 1 : 0;
setsockopt(sockfd_, SOL_SOCKET, SO_REUSEADDR,
&optval, sizeof optval);
// FIXME CHECK
}
~Socket()
{
close(sockfd_);
}
int fd() { return sockfd_; }
void Bind()
{
struct sockaddr_in my_addr;
bzero(&my_addr,sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(port_); //port
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
int err_log=bind(sockfd_, (struct sockaddr*)&my_addr, sizeof(my_addr));
if(err_log!=0)
{
perror("bind");
close(sockfd_);
exit(-1);
}
}
void Listen()
{
int err_log = listen(sockfd_, 10);
if(err_log!=0)
{
perror("listen");
close(sockfd_);
exit(-1);
}
}
int Accept(struct sockaddr_in* peeraddr)
{
//struct sockaddr_in addr;
//bzero(&addr, sizeof addr);
//socklen_t addr_len=sizeof(addr);
//int connfd = accept(sockfd_, &addr, &addr_len);
bzero(peeraddr, sizeof(*peeraddr));
socklen_t peer