tcpServer
#pragma once
#include<iostream>
#include<string>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<typeinfo>
#include<exception>
#include<stdexcept>
#include<arpa/inet.h>
#include<netinet/ip.h>
#include<signal.h>
#include<sys/select.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
using namespace std;
#define BackLog 3
class TcpServer
{
public:
TcpServer() = delete;
TcpServer(const TcpServer& t) = delete;
TcpServer& operator=(const TcpServer& t) = delete;
static int Socket()
{
int lsock = socket(AF_INET,SOCK_STREAM,0);
if( lsock < 0 )
{
throw runtime_error(string("socket error"));
}
cout<<"Socket:lsock:"<<lsock<<endl;
return lsock;
}
static void Bind(int lsock,int port)
{
sockaddr_in local;
local.sin_family = AF_INET;
local.sin_port = htons(port);
local.sin_addr.s_addr = INADDR_ANY;
if( bind(lsock,(struct sockaddr*)&local,sizeof(local)) < 0 )
{
throw runtime_error(string("bind error"));
}
cout<<"Bind success..."<<endl;
}
static void Listen(int lsock)
{
if( listen(lsock,BackLog) < 0 )
{
throw runtime_error(string("listen error"));
}
cout<<"Listen success..."<<endl;
}
static int Accept(int lsock)
{
sockaddr_in end_point;
socklen_t len = sizeof(end_point);
int sock = accept(lsock,(struct sockaddr*)&end_point,&len);
if( sock < 0 )
{
cout<<"this time accept fail ..."<<endl;
return -1;
}
else{
return sock;
}
}
~TcpServer()
{}
private:
};
SelectServer
#pragma once
#include "tcpServer.hpp"
#define NUM (sizeof(fd_set)*8)
#define DFL -1
class SelectServer
{
public:
SelectServer(int port= 8080)
:_port(port)
{
for(int i=0; i < static_cast<int>NUM; i++) _rfd_array[i] = _wfd_array[i] = DFL;
}
void SelectServerInit()
{
try{
_lsock = TcpServer::Socket();
TcpServer::Bind(_lsock,_port);
TcpServer::Listen(_lsock);
_rfd_array[0] = _lsock;
cout<<"_lsock"<<_lsock<<endl;
}
catch(exception& e)
{
cout<<"SelectServerInit"<<" "<<e.what()<<endl;
}
}
void SelectServerStart()
{
while(1)
{
int nfds = 0;
/*由于输入型和输出型参数合二为一,要每次进行select的*readfds和*writefds的重新绑定以及新文件描述符的绑定*/
fd_set rfds,wfds;
FD_ZERO(&rfds);FD_ZERO(&wfds);
for(int i = 0 ; i < static_cast<int>NUM; i++)
{
if( _rfd_array[i] != DFL )
{
FD_SET(_rfd_array[i],&rfds);
nfds = max(nfds, _rfd_array[i]);
}
if( _wfd_array[i] != DFL )
{
FD_SET(_wfd_array[i],&wfds);
nfds = max(nfds,_wfd_array[i]);
}
}
struct timeval timeout;
timeout.tv_sec = 10;
timeout.tv_usec = 0;
cout<<"nfds="<<nfds<<endl;
cout<<endl;
cout<<"select begin..."<<endl;
switch(select(nfds+1,&rfds,&wfds,nullptr,&timeout))
{
case 0:
cout<<" timeout..." << endl;
break;
case -1:
cerr<<"select error..."<<endl;
break;
default:
cout<<"Rervice()"<<endl;
Rervice(&rfds , &wfds);
break;
}
}
}
void Rervice( fd_set* rfds , fd_set* wfds )
{
for(int i =0 ; i < static_cast<int>NUM ; i++ )
{
if( _rfd_array[i] == DFL ) continue;
if( FD_ISSET ( _rfd_array[i] , rfds ) )
{
if( _rfd_array[i] == _lsock )
{
int sock = TcpServer::Accept(_lsock);
if( sock >=0 )
{
cout<<"get a new link..."<<endl;
}
Add2ReadFD(sock);
}
else//给读使用的,此时数据已经就绪不会发生阻塞,直接进行拷贝,要考虑到recv收到的字节数符合应用层协议
{
//考虑应用层协议的在epoll的demo中实现
char buf[10240];
//bug!
int recnum = recv(_rfd_array[i] , buf , (int)sizeof(buf)-1 , 0 );
if(recnum > 0)
{
cout<<"echo #:receive "<<recnum<<"bytes :"<< buf << endl;
}
else if( recnum == 0 )
{
cout<<"client quit..."<<endl;
}
Add2WriteFD(_rfd_array[i]);//修改为写事件
DelFromReadFD(i);
}
}
else if( FD_ISSET(_wfd_array[i],wfds) )
{
char buf[10240] = {" I am received . connect is over . good bye\n"};
send(_wfd_array[i] , buf, sizeof(buf) , 0);
close(_wfd_array[i]);
DelFromWriteFD(i);
}
}
}
void Add2ReadFD(int fd)
{
int i = 0;
for( ; i < static_cast<int>NUM ; i++)
{
if( _rfd_array[i] == DFL){
break;
}
}
if( i >= static_cast<int>NUM )
{
cerr <<"fd array is full"<<endl;
close(fd);
}
else{
_rfd_array[i] = fd;
cout<<"readfd :"<<fd<<endl;
}
}
void Add2WriteFD(int fd)
{
int i = 0;
for( ; i< static_cast<int>NUM ; i++ )
{
if( _wfd_array[i] == DFL )
{
break;
}
}
if( i>= static_cast<int> NUM )
{
cout<<"_wfd_array is full ..."<<endl;
close(fd);
}
else{
_wfd_array[i] = fd;
cout<<"writefd :"<<fd<<endl;
}
}
void DelFromReadFD(int idx)
{
if( idx >=0 && idx < static_cast<int>NUM ) _rfd_array[idx] = DFL;
}
void DelFromWriteFD(int idx)
{
if( idx >=0 && idx < static_cast<int>NUM ) _wfd_array[idx] = DFL;
}
~SelectServer()
{}
private:
int _lsock;
int _port;
int _rfd_array[NUM];
int _wfd_array[NUM];
};