实现停止并等待ARQ

时间:2015-03-16 04:19:38

标签: c++ sockets

我正在尝试模拟协议。这是我到目前为止所做的: 接收方代码:

// SocketException class


#ifndef SocketException_class
#define SocketException_class

#include <string>

class SocketException
{
 public:
  SocketException ( std::string s ) : m_s ( s ) {};
  ~SocketException (){};

  std::string description() { return m_s; }

 private:

  std::string m_s;

};

#endif

// Definition of the Socket class

#ifndef Socket_class
    #define Socket_class


    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <unistd.h>
    #include <string>
    #include <arpa/inet.h>


    const int MAXHOSTNAME = 200;
    const int MAXCONNECTIONS = 5;
    const int MAXRECV = 500;

    class Socket
    {
     public:
      Socket();
      virtual ~Socket();

      // Server initialization
      bool create();
      bool bind ( const int port );
      bool listen() const;
      bool accept ( Socket& ) const;

      // Client initialization
      bool connect ( const std::string host, const int port );

      // Data Transimission
      bool send ( const std::string ) const;
      int recv ( std::string& ) const;


      void set_non_blocking ( const bool );

      bool is_valid() const { return m_sock != -1; }

     private:

      int m_sock;
      sockaddr_in m_addr;


    };


#endif

// Implementation of the Socket class.

#include "string.h"
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include<iostream>


Socket::Socket() :
  m_sock ( -1 )
{

  memset ( &m_addr,
       0,
       sizeof ( m_addr ) );

}

Socket::~Socket()
{
  if ( is_valid() )
    ::close ( m_sock );
}

bool Socket::create()
{
  m_sock = socket ( AF_INET,
            SOCK_STREAM,
            0 );

  if ( ! is_valid() )
    return false;


  // TIME_WAIT - argh
  int on = 1;
  if ( setsockopt ( m_sock, SOL_SOCKET, SO_REUSEADDR, ( const char* ) &on, sizeof ( on ) ) == -1 )
    return false;


  return true;

}



bool Socket::bind ( const int port )
{

  if ( ! is_valid() )
    {
      return false;
    }



  m_addr.sin_family = AF_INET;
  m_addr.sin_addr.s_addr = INADDR_ANY;
  m_addr.sin_port = htons ( port );

  int bind_return = ::bind ( m_sock,
                 ( struct sockaddr * ) &m_addr,
                 sizeof ( m_addr ) );


  if ( bind_return == -1 )
    {
      return false;
    }

  return true;
}


bool Socket::listen() const
{
  if ( ! is_valid() )
    {
      return false;
    }

  int listen_return = ::listen ( m_sock, MAXCONNECTIONS );


  if ( listen_return == -1 )
    {
      return false;
    }

  return true;
}


bool Socket::accept ( Socket& new_socket ) const
{
  int addr_length = sizeof ( m_addr );
  new_socket.m_sock = ::accept ( m_sock, ( sockaddr * ) &m_addr, ( socklen_t * ) &addr_length );

  if ( new_socket.m_sock <= 0 )
    return false;
  else
    return true;
}


bool Socket::send ( const std::string s ) const
{
  int status = ::send ( m_sock, s.c_str(), s.size(), MSG_NOSIGNAL );
  if ( status == -1 )
    {
      return false;
    }
  else
    {
      return true;
    }
}


int Socket::recv ( std::string& s ) const
{
  char buf [ MAXRECV + 1 ];

  s = "";

  memset ( buf, 0, MAXRECV + 1 );

  int status = ::recv ( m_sock, buf, MAXRECV, 0 );

  if ( status == -1 )
    {
      std::cout << "status == -1   errno == " << errno << "  in Socket::recv\n";
      return 0;
    }
  else if ( status == 0 )
    {
      return 0;
    }
  else
    {
      s = buf;
      return status;
    }
}



bool Socket::connect ( const std::string host, const int port )
{
  if ( ! is_valid() ) return false;

  m_addr.sin_family = AF_INET;
  m_addr.sin_port = htons ( port );

  int status = inet_pton ( AF_INET, host.c_str(), &m_addr.sin_addr );

  if ( errno == EAFNOSUPPORT ) return false;

  status = ::connect ( m_sock, ( sockaddr * ) &m_addr, sizeof ( m_addr ) );

  if ( status == 0 )
    return true;
  else
    return false;
}

void Socket::set_non_blocking ( const bool b )
{

  int opts;

  opts = fcntl ( m_sock,
         F_GETFL );

  if ( opts < 0 )
    {
      return;
    }

  if ( b )
    opts = ( opts | O_NONBLOCK );
  else
    opts = ( opts & ~O_NONBLOCK );

  fcntl ( m_sock,
      F_SETFL,opts );

}

// Definition of the ServerSocket class

#ifndef ServerSocket_class
    #define ServerSocket_class

    class ServerSocket : private Socket
    {
     public:

      ServerSocket ( int port );
      ServerSocket (){};
      virtual ~ServerSocket();

      const ServerSocket& operator << ( const std::string& ) const;
      const ServerSocket& operator >> ( std::string& ) const;

      void accept ( ServerSocket& );

    };
#endif

// Implementation of the ServerSocket class

ServerSocket::ServerSocket ( int port )
{
  if ( ! Socket::create() )
    {
      throw SocketException ( "Could not create server socket." );
    }

  if ( ! Socket::bind ( port ) )
    {
      throw SocketException ( "Could not bind to port." );
    }

  if ( ! Socket::listen() )
    {
      throw SocketException ( "Could not listen to socket." );
    }

}

ServerSocket::~ServerSocket()
{
}


const ServerSocket& ServerSocket::operator << ( const std::string& s ) const
{
  if ( ! Socket::send ( s ) )
    {
      throw SocketException ( "Could not write to socket." );
    }

  return *this;

}


const ServerSocket& ServerSocket::operator >> ( std::string& s ) const
{
  if ( ! Socket::recv ( s ) )
    {
      throw SocketException ( "Could not read from socket." );
    }

  return *this;
}

void ServerSocket::accept ( ServerSocket& sock )
{
  if ( ! Socket::accept ( sock ) )
    {
      throw SocketException ( "Could not accept socket." );
    }
}

#include <string>

using namespace std;
int main ( int argc, int argv[] )
{
  cout << "Waiting to receive frames...\n";

  try
    {
      // Create the socket
      ServerSocket server ( 30000 );

      while ( true )
    {

      ServerSocket new_sock;
      server.accept ( new_sock );

      try
        {
            while ( true )
            {
              string data;
              cout<<"Recieving  data."; //not being displayed
              new_sock >> data;
              cout<<"Recieved data. Sending back the acknowledgment";
              new_sock << data;
            }
        }
      catch ( SocketException& ) {}

    }
    }
  catch ( SocketException& e )
    {
      std::cout << "Exception was caught:" << e.description() << "\nExiting.\n";
    }

  return 0;
}

发件人方码:

// SocketException class


#ifndef SocketException_class
#define SocketException_class

#include <string>

class SocketException
{
 public:
  SocketException ( std::string s ) : m_s ( s ) {};
  ~SocketException (){};

  std::string description() { return m_s; }

 private:

  std::string m_s;

};

#endif

// Definition of the Socket class

#ifndef Socket_class
    #define Socket_class


    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <unistd.h>
    #include <string>
    #include <arpa/inet.h>


    const int MAXHOSTNAME = 200;
    const int MAXCONNECTIONS = 5;
    const int MAXRECV = 500;

    class Socket
    {
     public:
      Socket();
      virtual ~Socket();

      // Server initialization
      bool create();
      bool bind ( const int port );
      bool listen() const;
      bool accept ( Socket& ) const;

      // Client initialization
      bool connect ( const std::string host, const int port );

      // Data Transimission
      bool send ( const std::string ) const;
      int recv ( std::string& ) const;


      void set_non_blocking ( const bool );

      bool is_valid() const { return m_sock != -1; }

     private:

      int m_sock;
      sockaddr_in m_addr;


    };


#endif

// Implementation of the Socket class.

#include "string.h"
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include<iostream>


Socket::Socket() :
  m_sock ( -1 )
{

  memset ( &m_addr,
       0,
       sizeof ( m_addr ) );

}

Socket::~Socket()
{
  if ( is_valid() )
    ::close ( m_sock );
}

bool Socket::create()
{
  m_sock = socket ( AF_INET,
            SOCK_STREAM,
            0 );

  if ( ! is_valid() )
    return false;


  // TIME_WAIT - argh
  int on = 1;
  if ( setsockopt ( m_sock, SOL_SOCKET, SO_REUSEADDR, ( const char* ) &on, sizeof ( on ) ) == -1 )
    return false;


  return true;

}



bool Socket::bind ( const int port )
{

  if ( ! is_valid() )
    {
      return false;
    }



  m_addr.sin_family = AF_INET;
  m_addr.sin_addr.s_addr = INADDR_ANY;
  m_addr.sin_port = htons ( port );

  int bind_return = ::bind ( m_sock,
                 ( struct sockaddr * ) &m_addr,
                 sizeof ( m_addr ) );


  if ( bind_return == -1 )
    {
      return false;
    }

  return true;
}


bool Socket::listen() const
{
  if ( ! is_valid() )
    {
      return false;
    }

  int listen_return = ::listen ( m_sock, MAXCONNECTIONS );


  if ( listen_return == -1 )
    {
      return false;
    }

  return true;
}


bool Socket::accept ( Socket& new_socket ) const
{
  int addr_length = sizeof ( m_addr );
  new_socket.m_sock = ::accept ( m_sock, ( sockaddr * ) &m_addr, ( socklen_t * ) &addr_length );

  if ( new_socket.m_sock <= 0 )
    return false;
  else
    return true;
}


bool Socket::send ( const std::string s ) const
{
  int status = ::send ( m_sock, s.c_str(), s.size(), MSG_NOSIGNAL );
  if ( status == -1 )
    {
      return false;
    }
  else
    {
      return true;
    }
}


int Socket::recv ( std::string& s ) const
{
  char buf [ MAXRECV + 1 ];

  s = "";

  memset ( buf, 0, MAXRECV + 1 );

  int status = ::recv ( m_sock, buf, MAXRECV, 0 );

  if ( status == -1 )
    {
      std::cout << "status == -1   errno == " << errno << "  in Socket::recv\n";
      return 0;
    }
  else if ( status == 0 )
    {
      return 0;
    }
  else
    {
      s = buf;
      return status;
    }
}



bool Socket::connect ( const std::string host, const int port )
{
  if ( ! is_valid() ) return false;

  m_addr.sin_family = AF_INET;
  m_addr.sin_port = htons ( port );

  int status = inet_pton ( AF_INET, host.c_str(), &m_addr.sin_addr );

  if ( errno == EAFNOSUPPORT ) return false;

  status = ::connect ( m_sock, ( sockaddr * ) &m_addr, sizeof ( m_addr ) );

  if ( status == 0 )
    return true;
  else
    return false;
}

void Socket::set_non_blocking ( const bool b )
{

  int opts;

  opts = fcntl ( m_sock,
         F_GETFL );

  if ( opts < 0 )
    {
      return;
    }

  if ( b )
    opts = ( opts | O_NONBLOCK );
  else
    opts = ( opts & ~O_NONBLOCK );

  fcntl ( m_sock,
      F_SETFL,opts );

}

// Definition of the ClientSocket class

#ifndef ClientSocket_class
    #define ClientSocket_class

    class ClientSocket : private Socket
    {
     public:

      ClientSocket ( std::string host, int port );
      virtual ~ClientSocket(){};

      const ClientSocket& operator << ( const std::string& ) const;
      const ClientSocket& operator >> ( std::string& ) const;

    };

#endif

// Implementation of the ClientSocket class



ClientSocket::ClientSocket ( std::string host, int port )
{
  if ( ! Socket::create() )
    {
      throw SocketException ( "Could not create client socket." );
    }

  if ( ! Socket::connect ( host, port ) )
    {
      throw SocketException ( "Could not bind to port." );
    }

}


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 <iostream>
#include <string>
using namespace std;

int main ( int argc, int argv[] )
{
  try
    {

      ClientSocket client_socket ( "localhost", 30000 );

      string reply, message;

      while(1){
          try{
              cout<<"Enter the frame to be sent: ";
              cin>>message;
              client_socket << message;
              client_socket >> reply;
          }
          catch ( SocketException& ) {}

          cout << "We received this response from the server:\n\"" << reply << "\"\n";
      }
    }
  catch ( SocketException& e )
    {
      cout << "Exception was caught:" << e.description() << "\n";
    }

  return 0;
}

在接收方侧代码中,在main()功能中,它正在从发送方接收数据,但我无法在接收方终端上显示它。 cout声明不起作用。代码有什么问题?

0 个答案:

没有答案