📄 unixsocket.cpp
字号:
//// This file is part of the "More for C++" library//// Copyright (c) 1999-2003 by Thorsten Goertz (thorsten@morefor.org)//// The "More for C++" library is free software; you can redistribute it and/or// modify it under the terms of the license that comes with this package.//// Read "license.txt" for more details.//// THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED// WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES// OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.////////////////////////////////////////////////////////////////////////////////#include <malloc.h>#include <netdb.h>#include <string.h>#include <unistd.h>#include <arpa/inet.h>#include <more/create.hpp>#include "unixsocket.hpp"using namespace more;using namespace more::io;using namespace more::os;using namespace more::os::unix_;////////////////////////////////////////////////////////////////////////////////UnixSocketAddress::UnixSocketAddress( struct sockaddr_in& rSockAddrIn): m_rSockAddrIn( rSockAddrIn ){}////////////////////////////////////////////////////////////////////////////////void UnixSocketAddress::resolve( const String& sNameOfHost, int nNoOfPort) throw( IOException ){ m_rSockAddrIn.sin_family = PF_INET; m_rSockAddrIn.sin_addr.s_addr = inet_addr( sNameOfHost ); m_rSockAddrIn.sin_port = htons( ( u_short ) nNoOfPort ); if( m_rSockAddrIn.sin_addr.s_addr == INADDR_NONE ) { struct hostent* pHost = gethostbyname( sNameOfHost ); if( pHost == 0 ) { throw IOException( -1, "Could not resolve name of host" ); } memcpy( &m_rSockAddrIn.sin_addr, pHost -> h_addr, pHost -> h_length ); }}////////////////////////////////////////////////////////////////////////////////UnixAcceptorSocket::UnixAcceptorSocket( ){ m_socket = socket( PF_INET, SOCK_STREAM, 0 ); m_nNoOfPort = -1; m_bHasBeenCancelled = false;}////////////////////////////////////////////////////////////////////////////////bool UnixAcceptorSocket::isValid( ) const{ return m_socket != -1;}////////////////////////////////////////////////////////////////////////////////void UnixAcceptorSocket::bind( const String& sNameOfHost, size_t nNoOfPort) throw( IOException ){ throwIfNotValid( ); int nResult = 0; memset( &m_sockAddrIn, 0, sizeof( sockaddr_in ) ); if( sNameOfHost.getLength( ) == 0 ) { m_sockAddrIn.sin_family = PF_INET; m_sockAddrIn.sin_addr.s_addr = INADDR_ANY; m_sockAddrIn.sin_port = htons( ( u_short ) nNoOfPort ); } else { UnixSocketAddress address( m_sockAddrIn ); address.resolve( sNameOfHost, nNoOfPort ); } nResult = ::bind( m_socket, ( const sockaddr* ) &m_sockAddrIn, sizeof( sockaddr_in ) ); if( nResult == 0 ) { socklen_t nSizeOfAddr = sizeof( sockaddr_in ); nResult = ::getsockname( m_socket, ( sockaddr* ) &m_sockAddrIn, &nSizeOfAddr ); if( nResult == 0 ) { m_nNoOfPort = ntohs( m_sockAddrIn.sin_port ); } } if( nResult != 0 ) { close( ); throw IOException( -1, "Unable to bind socket" ); }}////////////////////////////////////////////////////////////////////////////////void UnixAcceptorSocket::bind( size_t nNoOfPort) throw( IOException ){ bind( "", nNoOfPort );}////////////////////////////////////////////////////////////////////////////////String UnixAcceptorSocket::getNameOfHost( ) const{ char sNameOfHost[512]; gethostname( sNameOfHost, 511 ); return sNameOfHost;}////////////////////////////////////////////////////////////////////////////////size_t UnixAcceptorSocket::getNoOfPort( ) const{ return m_nNoOfPort;}////////////////////////////////////////////////////////////////////////////////p<Socket> UnixAcceptorSocket::accept( ) throw( IOException ){ throwIfNotValid( ); p<Socket> pResult; int nResultOfListen = -1; int socket = -1; struct sockaddr_in sockAddrIn; socklen_t sizeOfSockAddrIn = sizeof( sockaddr_in ); nResultOfListen = ::listen( m_socket, 1 ); if( nResultOfListen < 0 ) { throw IOException( -1, "Error while listening to socket" ); } socket = ::accept( m_socket, ( sockaddr* ) &sockAddrIn, &sizeOfSockAddrIn ); if( !m_bHasBeenCancelled ) { if( socket == -1 ) { throw IOException( -1, "Error while accepting socket" ); } pResult = CREATE UnixSocket( socket, sockAddrIn ); } return pResult;}////////////////////////////////////////////////////////////////////////////////void UnixAcceptorSocket::cancel( ) throw( IOException ){ throwIfNotValid( ); m_bHasBeenCancelled = true; ::close( m_socket ); m_socket = -1;}////////////////////////////////////////////////////////////////////////////////void UnixAcceptorSocket::close( ) throw( IOException ){ if( m_bHasBeenCancelled ) { m_bHasBeenCancelled = false; } else { throwIfNotValid( ); ::close( m_socket ); m_socket = -1; }}////////////////////////////////////////////////////////////////////////////////void UnixAcceptorSocket::finalize( ){ if( isValid( ) ) { close( ); }}////////////////////////////////////////////////////////////////////////////////UnixSocket::UnixSocket( ){ m_socket = socket( PF_INET, SOCK_STREAM, 0 ); m_bHasBeenConnected = false;}////////////////////////////////////////////////////////////////////////////////UnixSocket::UnixSocket( int socket, sockaddr_in& rSockAddrIn): m_socket( socket ), m_sockAddrIn( rSockAddrIn ){ m_bHasBeenConnected = true;}////////////////////////////////////////////////////////////////////////////////bool UnixSocket::isValid( ) const{ return m_socket != -1;}////////////////////////////////////////////////////////////////////////////////void UnixSocket::connect( const String& sNameOfHost, size_t nNoOfPort) throw( IOException ){ throwIfNotValid( ); UnixSocketAddress address( m_sockAddrIn ); int nResultOfConnect = -1; if( m_bHasBeenConnected ) { throw IOException( -1, "Socket has already been connected" ); } address.resolve( sNameOfHost, nNoOfPort ); nResultOfConnect = ::connect( m_socket, ( const sockaddr* ) &m_sockAddrIn, sizeof( sockaddr_in ) ); if( nResultOfConnect < 0 ) { throw IOException( -1, "Unable to connect to socket" ); } m_bHasBeenConnected = true;}////////////////////////////////////////////////////////////////////////////////String UnixSocket::getNameOfHost( ) const{ int nErrorCode; sockaddr_in address; socklen_t nSizeOfBuffer = sizeof( address ); nErrorCode = getpeername( m_socket, ( struct sockaddr* ) &address, &nSizeOfBuffer ); if( nErrorCode != 0 ) { throw IOException( nErrorCode, "UnixSocket::getNameOfHost failed" ); } return inet_ntoa( address.sin_addr );}////////////////////////////////////////////////////////////////////////////////size_t UnixSocket::getNoOfPort( ) const{ return m_sockAddrIn.sin_port;}////////////////////////////////////////////////////////////////////////////////p<InputStream> UnixSocket::getInputStream( ) throw( IOException ){ throwIfNotConnected( ); return CREATE UnixSocketInputStream( this );}////////////////////////////////////////////////////////////////////////////////p<OutputStream> UnixSocket::getOutputStream( ) throw( IOException ){ throwIfNotConnected( ); return CREATE UnixSocketOutputStream( this );}////////////////////////////////////////////////////////////////////////////////void UnixSocket::close( ) throw( IOException ){ throwIfNotValid( ); m_bHasBeenConnected = false; ::close( m_socket ); m_socket = -1;}////////////////////////////////////////////////////////////////////////////////void UnixSocket::finalize( ){ if( isValid( ) ) { close( ); }}////////////////////////////////////////////////////////////////////////////////size_t UnixSocket::available( ) throw( IOException ){ throwIfNotConnected( ); return 0;}////////////////////////////////////////////////////////////////////////////////bool UnixSocket::hasBeenClosed( ) throw( IOException ){ throwIfNotConnected( ); return m_socket == -1;}////////////////////////////////////////////////////////////////////////////////size_t UnixSocket::skip( size_t bytesToSkip) throw( IOException ){ size_t bytesLeftToSkip = bytesToSkip; void* pBuffer = malloc( 4096 ); while( bytesLeftToSkip > 4096 ) { read( pBuffer, 4096 ); bytesLeftToSkip -= 4096; } if( bytesLeftToSkip > 0 ) { read( pBuffer, bytesLeftToSkip ); } free( pBuffer ); return bytesToSkip;}////////////////////////////////////////////////////////////////////////////////size_t UnixSocket::read( void* pBuffer, size_t nMaxNoOfBytes) throw( IOException ){ throwIfNotValid( ); throwIfNotConnected( ); int nNoOfReceivedBytes = recv( m_socket, ( char* ) pBuffer, nMaxNoOfBytes, 0 ); if( nNoOfReceivedBytes < 0 ) { throw IOException( -1, "Error while reading from socket" ); } return ( size_t ) nNoOfReceivedBytes;}////////////////////////////////////////////////////////////////////////////////void UnixSocket::write( const void* pBuffer, size_t nNoOfBytes) throw( IOException ){ throwIfNotValid( ); throwIfNotConnected( ); int nNoOfSentBytes = ::send( m_socket, ( const char* ) pBuffer, nNoOfBytes, 0 ); if( nNoOfSentBytes <= 0 ) { throw IOException( -1, "Error while writing to socket" ); }}////////////////////////////////////////////////////////////////////////////////size_t UnixSocket::rewind( size_t nNoOfBytes) throw( IOException ){ throw IOException( 0, "Rewind on this output-stream not supported" ); return 0;}////////////////////////////////////////////////////////////////////////////////void UnixSocket::flush( ) throw( IOException ){ throwIfNotValid( ); throwIfNotConnected( );}////////////////////////////////////////////////////////////////////////////////UnixSocketInputStream::UnixSocketInputStream( const p<UnixSocket>& pUnixSocket): m_pUnixSocket( pUnixSocket ){}////////////////////////////////////////////////////////////////////////////////size_t UnixSocketInputStream::available( ) throw( IOException ){ return m_pUnixSocket -> available( );}////////////////////////////////////////////////////////////////////////////////bool UnixSocketInputStream::hasBeenClosed( ) throw( IOException ){ return m_pUnixSocket -> hasBeenClosed( );}////////////////////////////////////////////////////////////////////////////////size_t UnixSocketInputStream::skip( size_t nNoOfBytes) throw( IOException ){ return m_pUnixSocket -> skip( nNoOfBytes );}////////////////////////////////////////////////////////////////////////////////size_t UnixSocketInputStream::read( void* pBuffer, size_t nMaxNoOfBytes) throw( IOException ){ return m_pUnixSocket -> read( pBuffer, nMaxNoOfBytes );}////////////////////////////////////////////////////////////////////////////////UnixSocketOutputStream::UnixSocketOutputStream( const p<UnixSocket>& pUnixSocket): m_pUnixSocket( pUnixSocket ){}////////////////////////////////////////////////////////////////////////////////void UnixSocketOutputStream::write( const void* pBuffer, size_t nNoOfBytes) throw( IOException ){ m_pUnixSocket -> write( pBuffer, nNoOfBytes );}////////////////////////////////////////////////////////////////////////////////size_t UnixSocketOutputStream::rewind( size_t nNoOfBytes) throw( IOException ){ return m_pUnixSocket -> rewind( nNoOfBytes );}////////////////////////////////////////////////////////////////////////////////bool UnixSocketOutputStream::hasBeenClosed( ) throw( IOException ){ return m_pUnixSocket -> hasBeenClosed( );}////////////////////////////////////////////////////////////////////////////////void UnixSocketOutputStream::flush( ) throw( IOException ){ m_pUnixSocket -> flush( );}////////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -