Sign in to follow this  

Howto get available space left of internal writebuffer of a socket [win32]

This topic is 4728 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, Could anybody please help me with how to get the state of the internal writebuffer of a socket under windows. In other words, how many bytes are left in the internal writebuffer of the socket. The only thing I could find was how to set and get the internal writebuffer size with WSAIoctl. Okee, a little story about the project. I am making a VFW video capture, MPEG4 encoder, tcp streaming ActiveX component. Everything is written in pure C++ and win32. So no (censured) MFC or ATL ;). Before I encode a mpeg4 frame I have to know if I can send the frame. Because a MPEG4 frame is the difference between the current and the previous frame, except for GOP frames. Thanks a lot and happy new year, Bagwani [Edited by - bagwani on December 31, 2004 1:23:22 PM]

Share this post


Link to post
Share on other sites
Well, the best I can come up with is if a socket is ready to write. Here is the c++ snippet.


bool CanWrite( int SocketDescriptor)
{
if( SocketDescriptor == 0 )
{
return false;
}


fd_set writefds;

FD_ZERO( &writefds );
FD_SET( SocketDescriptor, &writefds );

int result = -1;
result = select( SocketDescriptor, 0, &writefds, 0, 0 );

return ( 0 == result );
}




But I still don't know how MUCH I can write to the socket. Anybody can help me out with that???

[Edited by - bagwani on December 31, 2004 10:52:43 AM]

Share this post


Link to post
Share on other sites
I'm debugging a program where I use sockets (with MFC) and I test if all the data has been sent over the socket checking the result of send. I'll translate avoiding MFC. For example:


int nBytesToSend=1000;
char * pBuffer=new char[nBytesToSend];
int nBytesSent=send(hSocket,pBuffer,nBytesToSend,0);

if (nBytesSent<nBytesToSend)
nBytesLeftToBeSend=nBytesToSend-nBytesSent; // <- your value of interest?


If this answer is not what you're expecting, I try one another [embarrass].

getsockopt with parameter SO_MAX_MSG_SIZE tell you the max size of a message (I think that's the size of the internal buffer) and when send return the error code WSAEMSGSIZE, you know that nothing is sent. So with simple substraction you'll know how many bytes of SO_MAX_MSG_SIZE are left.

Hope that's help.

Share this post


Link to post
Share on other sites
@hplus0603

I forgot to mention my sockets are in non-blocking mode. If I write to the socket, it will never be blocked.

@Fill

The problem is that I must send the whole mpeg4 encoded frame or not. If I send it partially, I screw up the decoder on the other end. So If I could peek in the internal writebuffer of the socket, I know if there is a queue building up and can avoid of sending incomplete MPEG4 frames. BTW I'm using FFMPEG for the en/decoding.

I am also programming under unix and linux. And there it is possible to look at the available space left of the internal writebuffer of the socket.

@both

Thanks for the input

[Edited by - bagwani on December 31, 2004 12:26:28 PM]

Share this post


Link to post
Share on other sites
@Fil: When send() returns, that just means the data has been copied to internal buffers, it's not guaranteed that the data is at the other end, or has been acknowledged.


@bagwani: I still don't understand what the difference between "enough buffer space" or not, is. Why would the decoder be confused? Are you using TCP or UDP? If you're using UDP, you'd have to worry about packet loss and stuff anyway, so fragmenting packets wouldn't be a problem. If you're using TCP, you have to realize that it's a stream protocol, and thus you are NOT guaranteed to get a single packet of 200 bytes out one end if you write a single packet of 200 bytes on the sending side -- you might get two packets of 100 out, or one packet of 300 (if you had first written 100 bytes before the 200 bytes).

I'm guessing you're using TCP. TCP is a stream protocol. For your protocol to work right (i e, deliver "whole frames") you have to introduce your own framing. Thus, each time you write data, you first write a length, and then write that many bytes of data. On the receiving side, you read a length, and then that many bytes of data.

I still don't understand what you would do if you wouldn't write the data, though. If the link is lower bandwidth than the data rate of your video, then what? What if there's temporary congestion and the link dries up for a few seconds?

Share this post


Link to post
Share on other sites
just wondering TCP is streaming

that means it guarantees your packages will arrive and they will arive in the correct order


so all you do is create a timer to not overflow your connection and then simply send your data this needs some tweaking though but should work for what you are going to do

i am not sure but i think you can get the max packet size somehow just look up the msdn

Share this post


Link to post
Share on other sites
TCP guarantees that the data STREAM will arrive in order, even if it takes a 10 second stall of re-transmits to get it there.

Also, it guarantees that the ordered data gets there -- it does NOT guarantee that any specific packets get there. Thus, if you send(100 bytes) and then send(200 bytes) and then send(300 bytes), the other end may see 12 packets of 50 bytes each, or one packet of 600 bytes, or anything inbetween -- it's only the sequence of bytes that matters.

TCP implementations will typically coalesce successive writes, and, when packet re-transmits happen, coalesce packets waiting to be sent.

Share this post


Link to post
Share on other sites
Quote:
Original post by hplus0603
@Fil: When send() returns, that just means the data has been copied to internal buffers, it's not guaranteed that the data is at the other end, or has been acknowledged.


Sorry if I take advantage of this thread to ask what can be done to be sure data has been acknowledged. If the other end does a send() to tell me it has received my data, it is possible I can never receive it. (This could help me in solving a problem on the program on my thesis, if you want I can begin another thread).

Share this post


Link to post
Share on other sites
@hplus0603

I use TCP to transmit my data. First I send a header packet with a unique starting sequence, time stamp and the length of the data packet. After that I send the data packet.
I think I would solve this problem to just cache the last mpeg4 frame. So if I can't transmit the last frame, I keep it in a separate buffer. When the next frame is grabbed from the videograbber I will try to retransmit the last frame stored in the buffer and skip the current frame. But if I could peek in the writebuffer of the socket, I would not have to create an extra buffer. Anyways problem is solved.

Thanks

Share this post


Link to post
Share on other sites
It sounds like you maybe should consider turning off buffering altogether and use overlapped I/O instead. Basically you setsockopt SO_DONTLINGER to true and SO_SNDBUF to 0 and then manage your buffer directly. It's more work but you get better performance. I believe this is what microsoft recommends for streaming media anyway.

You still don't get everything. If nothing else you'll be limited by the TCP window size and ramp-up time. But that's life in TCP-city.

Share this post


Link to post
Share on other sites

This topic is 4728 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this