TCP socket : how to send more than GetTxAvailable() ?

41 views
Skip to first unread message

Segue Diallo

unread,
Apr 26, 2020, 8:44:52 PM4/26/20
to ns-3-users
socket->Send(buffer,size,0) returns -1 because of size > socket-> GetTxAvailable().

So, I tried to split 'buffer' to chunks of size chunk_size = GetTxAvailable(), and send each piece using different Ptr<Socket> instance.

But, the total buffer stills NOT RECEIVED.

Any suggestions will be appreciated.

Thanks in advance,
Diallo.

Segue Diallo

unread,
Apr 27, 2020, 5:27:51 PM4/27/20
to ns-3-users
I want to know when a new tx space become available.

--
Posting to this group should follow these guidelines https://www.nsnam.org/wiki/Ns-3-users-guidelines-for-posting
---
You received this message because you are subscribed to the Google Groups "ns-3-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ns-3-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ns-3-users/9316643c-0221-4cdf-81f5-31e1da53b852%40googlegroups.com.

Nguyen Viet Ha

unread,
Apr 28, 2020, 7:26:26 PM4/28/20
to ns-3-users
Hope it can help.

Socket->Connect (InetSocketAddress (servAddress, servPort));
Socket->SetSendCallback (MakeCallback (&WriteUntilBufferFull));      //Call WriteUntilBufferFull when one segment is send
WriteUntilBufferFull (localSocket, localSocket->GetTxAvailable());   //Put new data having the size of localSocket->GetTxAvailable() to TCP

void WriteUntilBufferFull (Ptr<Socket> localSocket, uint32_t txAvailable) {
   
//split 'buffer'
   
//...
    localSocket->Send (...) ;
}

Nguyen Viet Ha

unread,
Apr 28, 2020, 7:28:23 PM4/28/20
to ns-3-users
localSocket->GetTxAvailable()  -->   Socket->GetTxAvailable() 

Segue Diallo

unread,
Apr 28, 2020, 8:02:44 PM4/28/20
to ns-3-users
Hello,

Thanks for the respond,
 
I've tried that; in WriteUntilBufferFull(...) , I have :

void Rsu::WriteUntilBufferFull(Ptr<Socketsocktuint32_t txSpace)
{
    int size = m_buffer.size();
    if (size <= 0)
        return;
    //cout << " SocketSize :: " << sockt->GetTxAvailable() << endl;
    int packet_size;
    
    while (size > 0 && sockt->GetTxAvailable() > 0)
    {
        packet_size = min(size, (int)sockt->GetTxAvailable());
        packet_size = min(10000, packet_size);
        int error = sockt->Send(reinterpret_cast<const uint8_t *>(m_buffer.substr(0, packet_size).c_str()), packet_size, 0);
        cout << "error 0 : " << error << endl;
        if (error < 0)
        {
            return;
        }
        m_buffer.erase(0, packet_size);
        size -= packet_size;
    }
    
      
//if (size == 0)
     //sockt->Close();

}

I still don't receive the complete packet?

Is there any way to update the socket->GetTxAvailable() size if error <0?

Thanks,
Diallo


Le mer. 29 avr. 2020 à 01:28, Nguyen Viet Ha <nvha...@gmail.com> a écrit :
localSocket->GetTxAvailable()  -->   Socket->GetTxAvailable() 

--
Posting to this group should follow these guidelines https://www.nsnam.org/wiki/Ns-3-users-guidelines-for-posting
---
You received this message because you are subscribed to the Google Groups "ns-3-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ns-3-users+...@googlegroups.com.

Nguyen Viet Ha

unread,
Apr 28, 2020, 8:34:23 PM4/28/20
to ns-3-users
The "error" should not happen because you only send the data size equal to the Tx Buffer available.

Does your simulation not receive all data (1)? Or does it has a problem at the beginning?

If (1), I think the problem is that the data size is no equal n*TCP_Segment.
TCP still waits for the new data to fill all space one segment.
If the last data is not equal to one segment size, you should close the Socket to send all the remaining data.

Add something like this at end of WriteUntilBufferFull:
if (all data is sent) {
   localSocket->Close ();
}

Segue Diallo

unread,
Apr 28, 2020, 9:09:32 PM4/28/20
to ns-3-users
Maybe I got it wrong.
I have a Send(Mypacket packet, ..) method which ones evoked does two thinks:
  1. increment m_buffer with packet size
  2. Calls WriteUntilBufferFull(..)


void Rsu::Send(const MyPacket &p_packetconst uint32_t &p_id)
{
    auto ip4_address = GetIp4Address(p_id);
    Ptr<Socket> sockt;
    if (find(m_peers.begin(), m_peers.end(), p_id) != m_peers.end())
    {
        auto it = m_peersSockets.find(ip4_address);
        if (it == m_peersSockets.end())
        {
            //Create the socket if it doesn't exist
            m_peersSockets[ip4_address] = Socket::CreateSocket(GetNode(), TcpSocketFactory::GetTypeId());
            m_peersSockets[ip4_address]->Connect(InetSocketAddress(ip4_address, m_port));
            m_peersSockets[ip4_address]->SetSendCallback(MakeCallback(&Rsu::WriteUntilBufferFull, this));
        }
        sockt = m_peersSockets[ip4_address];
    }
    else
    { //not a peer
        auto it = m_rsusSockets.find(ip4_address);
        if (it == m_rsusSockets.end())
        {
            //Create the socket if it doesn't exist
            m_rsusSockets[ip4_address] = Socket::CreateSocket(GetNode(), TcpSocketFactory::GetTypeId());
            m_rsusSockets[ip4_address]->Connect(InetSocketAddress(ip4_address, m_port));
            m_rsusSockets[ip4_address]->SetSendCallback(MakeCallback(&Rsu::WriteUntilBufferFull, this));
        }
        sockt = m_rsusSockets[ip4_address];
    }
    m_buffer += p_packet.Serialize() + "#";
    WriteUntilBufferFull(sockt, sockt->GetTxAvailable());
}

void Rsu::WriteUntilBufferFull(Ptr<Socketsocktuint32_t txSpace)
{
    int size = m_buffer.size();
    if (size <= 0)
        return;
    //cout << " SocketSize :: " << sockt->GetTxAvailable() << endl;
    int packet_size;

    while (size > 0 && sockt->GetTxAvailable() > 0)
    {
        packet_size = min(size, (int)sockt->GetTxAvailable());
        packet_size = min(10000, packet_size);
        int error = sockt->Send(reinterpret_cast<const uint8_t *>(m_buffer.substr(0, packet_size).c_str()), packet_size, 0);
        cout << "error : " << error << endl;
        if (error < 0)
        {
            return;
        }
        m_buffer.erase(0, packet_size);
        size -= packet_size;
    }

    if (size == 0)
    {
        //sockt->Close();
    }

}



The problem is that I only read 131072 bytes (not the complete packet size).

Diallo.


--
Posting to this group should follow these guidelines https://www.nsnam.org/wiki/Ns-3-users-guidelines-for-posting
---
You received this message because you are subscribed to the Google Groups "ns-3-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ns-3-users+...@googlegroups.com.

Nguyen Viet Ha

unread,
Apr 28, 2020, 9:42:20 PM4/28/20
to ns-3-users
How many bytes are in the data? And how about the TCP segment size?
Did you check (1)?

Nguyen Viet Ha

unread,
Apr 28, 2020, 9:46:53 PM4/28/20
to ns-3-users
if (error < 0)

As I said, "error" should not occur.
However, if "error" happens, do you resend the data?

Segue Diallo

unread,
Apr 28, 2020, 9:56:07 PM4/28/20
to ns-3-users
Yes, I checked (1), TCP segment size = 10000.
I'm trying to send 165480 bytes, but I only received 131072 bytes.

if error <0, I suppose socket->SentSendCallBack(..) will call back WriteUntilBufferFull(..)

--
Posting to this group should follow these guidelines https://www.nsnam.org/wiki/Ns-3-users-guidelines-for-posting
---
You received this message because you are subscribed to the Google Groups "ns-3-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ns-3-users+...@googlegroups.com.

Nguyen Viet Ha

unread,
Apr 28, 2020, 10:18:23 PM4/28/20
to ns-3-users
There are at least two reasons for the received data < sent data:

(a) Missing data before forwarding to TCP Sending Buffer.
(b) The TCP connection suddenly fails (e.g., TCP timeout > 4 times, TCP session reset, etc).

For (a), please check that the "error" has happened or not? Why? You send the data = Buffer available => it is impossible to data > Buffer available.
For (b), please check the remaining data after transmission.


if error <0, I suppose socket->SentSendCallBack(..) will call back WriteUntilBufferFull(..)
The WriteUntilBufferFull is called only when a segment is sent. :-(

Nguyen Viet Ha

unread,
Apr 28, 2020, 10:57:14 PM4/28/20
to ns-3-users
Or please try to trace TcpSocketBase::Tx, TcpSocketBase::Rx to monitor the packet flow (SequenceNumber, ACK, etc).

DynamicCast<TcpSocketBase>(Socket)->TraceConnect("Tx","",MakeCallback (SendPacketToIP,this));
DynamicCast<TcpSocketBase>(Socket)->TraceConnect("Rx","",MakeCallback (ReceivePacketFromIP,this));


void SendPacketToIP(std::string context, Ptr<const Packet> p, const TcpHeader& h, Ptr<const TcpSocketBase> s){
    ...
}

void ReceivePacketFromIP (std::string context, Ptr<const Packet> p, const TcpHeader& h, Ptr<const TcpSocketBase> s){
    ...
}


Segue Diallo

unread,
May 5, 2020, 1:26:37 AM5/5/20
to ns-3-users

Hello,

I have solved the problem by increasing SndBufSize

e.g, 

uint32_t tcpSndBufSize=1000000;

Config::SetDefault("ns3::TcpSocket::SndBufSize"UintegerValue(tcpSndBufSize));

Diallo

Nguyen Viet Ha

unread,
May 5, 2020, 2:07:34 AM5/5/20
to ns-3-users
Dear Diallo,

If your purpose is only to focus on trying to send data, this solution is fine.

But a large TCP sending buffer size (SndBufSz) is not practical.
With your settings (SndBufSz > data size), the Sending function is actually called only one time. At other times, it is no data to send.

In your previous version, your application maybe not wait for the TCP (Sending buffer) ready; and thus cause the data loss.

Best,

Reply all
Reply to author
Forward
0 new messages