参考网上的实现方式,先实现一个初始的SOCKET类及客户端,服务器的继承类,后续打算实现C++ epoll的框架。现在把文件贴在下面
基类Socket.h, Socket.cpp
#ifndef _E_SOCKET_H_
#define _E_SOCKET_H_
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "basetype.h"
using namespace std;
const unsigned int BUFF_SIZE_1024 = 1024;
const unsigned int BUFF_SIZE_2048 = 2048;
/*
typedef union tagSOCK_ADDR
{
struct sockaddr_in m_addr;
struct addrinfo hints;
}SOCK_ADDR_U;
*/
class Socket
{
public:
Socket();
virtual ~Socket();
BOOL CreateSocket();
BOOL BindSocket(const UINT uiPort);
BOOL ListenSocket()const;
BOOL AcceptSocket(Socket & in_skt)const;
BOOL ConnectSocket(std::string host, const UINT uiPort);
VOID CloseSocket();
INT SetSocketNoblocking(BOOL no);
INT Send(const std::string &str)const;
INT Recv(std::string &str)const;
BOOL Is_Valid()const
{
return sockfd != -1;
}
private:
int sockfd;
struct sockaddr_in sock_addr;
};
#endif
#include "e_socket.h"
/**************************************************************************
* |
* Function Name : Socket.Socket
* Input :
* Author : lily
* Date : 2018-8-26
* Description :
* Return :
* |
**************************************************************************/
Socket::Socket()
{
memset(&sock_addr, 0, sizeof(sock_addr));
}
/**************************************************************************
* |
* Function Name : Socket.~Socket
* Input :
* Author : lily
* Date : 2018-8-26
* Description :
* Return :
* |
**************************************************************************/
Socket::~Socket()
{
if (!Is_Valid())
{
CloseSocket();
}
}
/**************************************************************************
* |
* Function Name : Socket.CreateSocket
* Input :
* Author : lily
* Date : 2018-8-26
* Description :
* Return :
* |
**************************************************************************/
BOOL Socket:: CreateSocket()
{
INT iRet = 0;
INT sockoptval = 1;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (!Is_Valid())
{
return false;
}
/* set reuse addr */
iRet = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockoptval, sizeof(sockoptval));
if (-1 == iRet)
{
return false;
}
return true;
}
/**************************************************************************
* |
* Function Name : Socket.BindSocket
* Input :
* Author : lily
* Date : 2018-8-26
* Description :
* Return :
* |
**************************************************************************/
BOOL Socket::BindSocket(const UINT uiPort)
{
INT iRet = 0;
if (!Is_Valid())
{
return false;
}
sock_addr.sin_family = AF_INET;
sock_addr.sin_addr.s_addr = INADDR_ANY;
sock_addr.sin_port = htons ( uiPort );
//inet_pton(AF_INET, pHost, &(sock_addr.sin_addr);
cout<<"server bind socket ..."<sockfd, (struct sockaddr *)&this->sock_addr,
(socklen_t *)&addr_len);
if (!in_skt.Is_Valid())
{
return false;
}
return true;
}
/**************************************************************************
* |
* Function Name : Socket.ConnectSocket
* Input :
* Author : lily
* Date : 2018-8-26
* Description :
* Return :
* |
**************************************************************************/
BOOL Socket::ConnectSocket(std::string host, const UINT uiPort)
{
INT iRet = 0;
if (!Is_Valid())
{
return false;
}
sock_addr.sin_family = AF_INET;
//sock_addr.sin_port = htonl(uiPort);
/*
inet_pton进行相反的转换,从数值格式(addrptr)转换到表达格式(strptr)。
函数尝试转换由strptr指针所指的字符串,并通过addrptr指针存放二进制结果。若成功则返回1,
否则如果对所指定的family而言输入的字符串不是有效的表达式,那么值为0。
返回:1——成功,0----输入不是有效的表达式,-1——出错;
inet_ntop进行相反的转换,从数值格式(addrptr)转换到表达格式(strptr)。
len参数是目标存储单元的大小,以免该函数溢出其调用者的缓冲区。
返回:指向结果的指针——成功,NULL——出错;
*/
cout<<"host.c_str"< iRcvLen)
{
cout<<"recv error "<
Server端继承Socket类
// Definition of the ServerSocket class
#ifndef ServerSocket_class
#define ServerSocket_class
#include "e_socket.h"
class ServerSocket : private Socket
{
public:
ServerSocket ( UINT port );
ServerSocket (){};
virtual ~ServerSocket();
const ServerSocket& operator << ( const std::string& ) const;
const ServerSocket& operator >> ( std::string& ) const;
void Accept ( ServerSocket& );
};
#endif
// Definition of the ServerSocket class
#include "e_server.h"
#include "SocketException.h"
ServerSocket::ServerSocket(UINT uiPort)
{
BOOL bRes = false;
bRes = Socket::CreateSocket();
if (false == bRes)
{
throw SocketException ( "Could not create server socket." );
}
bRes = Socket::BindSocket(uiPort);
if (false == bRes)
{
throw SocketException ( "Server Could not bind to port." );
}
bRes = Socket::ListenSocket();
if(false == bRes)
{
throw SocketException ( "Could not listen to socket." );
}
}
ServerSocket::~ServerSocket()
{
}
/**************************************************************************
* |
* Function Name : ServerSocket.Accept
* Input :
* Author : lily
* Date : 2018-8-26
* Description :
* Return :
* |
**************************************************************************/
void ServerSocket::Accept(ServerSocket &ser_skt)
{
cout<<"accept connect..."<> ( std::string& str ) const
{
if (! Socket::Recv(str))
{
throw SocketException ( "Could not read from socket." );
}
return *this;
}
Client 端继承Socket类
// Definition of the ClientSocket class
#ifndef ClientSocket_class
#define ClientSocket_class
#include "e_socket.h"
class ClientSocket : private Socket
{
public:
ClientSocket ( std::string host, UINT port );
virtual ~ClientSocket(){};
const ClientSocket& operator << ( const std::string& ) const;
const ClientSocket& operator >> ( std::string& ) const;
};
#endif
// Implementation of the ClientSocket class
#include "e_client.h"
#include "SocketException.h"
ClientSocket::ClientSocket ( std::string host, UINT port )
{
if ( ! Socket::CreateSocket() )
{
throw SocketException ( "Could not create client socket." );
}
if ( ! Socket::ConnectSocket(host, port))
{
throw SocketException ( "Could not connect to server." );
}
}
const ClientSocket& ClientSocket::operator << ( const std::string& s ) const
{
if ( ! Socket::Send(s) )
{
throw SocketException ( "Could not write to socket." );
}
return *this;
}
const ClientSocket& ClientSocket::operator >> ( std::string& s ) const
{
if ( ! Socket::Recv(s) )
{
throw SocketException ( "Could not read from socket." );
}
return *this;
}
服务器主函数部分 :
#include "SocketException.h"
#include "e_server.h"
int main ( int argc, char *argv[] )
{
std::cout << "running....\n";
try
{
// Create the socket
ServerSocket server ( 30000 );
while ( true )
{
ServerSocket new_sock;
server.Accept(new_sock);
try
{
while ( true )
{
std::string data;
new_sock >> data;/* operator << */
new_sock << data;/* operator >> */
}
}
catch ( SocketException& )
{
}
}
}
catch ( SocketException& e )
{
std::cout << "Exception was caught:" << e.description() << "\nExiting.\n";
}
return 0;
}
客户端主函数部分:
#include "e_client.h"
#include "SocketException.h"
#include
#include
int main ( int argc, char *argv[] )
{
try
{
ClientSocket client_socket ( "127.0.0.1", 30000 );
std::string reply;
try
{
client_socket << "Test message.";
client_socket >> reply;
}
catch ( SocketException& ) {}
std::cout << "We received this response from the server:\n\"" << reply << "\"\n";;
}
catch ( SocketException& e )
{
std::cout << "Exception was caught:" << e.description() << "\n";
}
return 0;
}
异常处理类
// SocketException class
#ifndef SocketException_class
#define SocketException_class
#include
class SocketException
{
public:
SocketException ( std::string s ) : m_s ( s ) {};
~SocketException (){};
std::string description() { return m_s; }
private:
std::string m_s;
};
#endif
效果:
客户端
li@li:~/C++/socket/client$ ./a.out
host.c_str127.0.0.1
inet_pton
connect server... host = 127.0.0.1 port = 30000
We received this response from the server:
"Test message."
服务器:
li@li:~/C++/socket/server$ ./a.out
running....
server bind socket ...
listening ...
accept connect...
remote socket closed
后续会在此基础上改进,并新增EPOLL类,丰富服务器处理类型