|
Well Judy, I had to test this before I respectfully disagreed with you
I respectfully disagree... A blocking Recv() WILL return before all bytes requested are
received.
Here's the test I did - note I try to recv 512 bytes but only send 256...
<font color="Green">
<font color="Green">
</font>UINT __cdecl TestThreadProc( LPVOID pParam )
{
SOCKET ListenSocket;
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ListenSocket == INVALID_SOCKET)
{
return 1;
}
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("127.0.0.1");
service.sin_port = htons(2460);
if (bind( ListenSocket, (SOCKADDR*) &service, sizeof(service)) == SOCKET_ERROR)
{
closesocket(ListenSocket);
return 1;
}
if (listen( ListenSocket, 1 ) == SOCKET_ERROR)
{
closesocket(ListenSocket);
return 1;
}
SOCKET AcceptSocket;
AcceptSocket = accept( ListenSocket, NULL, NULL );
if (AcceptSocket == INVALID_SOCKET)
{
closesocket(ListenSocket);
return 1;
}
BYTE *pBuf = new BYTE[512];
BYTE *pCurBuf = pBuf;
int BytesRemaining = 512;
while (BytesRemaining > 0)
{
int CurBytesReceived = ::recv(AcceptSocket, (char*)pCurBuf, BytesRemaining, 0);
if (CurBytesReceived == 0) <font color="Red">
{
break;
}
else if (CurBytesReceived == SOCKET_ERROR)
{
int rc = WSAGetLastError();
if (rc != WSAEWOULDBLOCK)
{
break;
}
}
else
{
BytesRemaining -= CurBytesReceived;
pCurBuf += CurBytesReceived;
}
}
delete[] pBuf;
closesocket(AcceptSocket);
closesocket(ListenSocket);
return 0;
}
<font color="Green">
void CMYTestDlg::OnOK()
{
AfxBeginThread(&TestThreadProc, NULL);
::Sleep(1000); <font color="Red">
SOCKET ConnectSocket;
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET)
{
return;
}
sockaddr_in clientService;
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
clientService.sin_port = htons( 2460 );
if ( connect( ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService) ) == SOCKET_ERROR)
{
return;
}
BYTE *pBuf = new BYTE[512];
send(ConnectSocket, (const char *)pBuf, 256, 0);
delete[] pBuf;
::MessageBox(*this, _T("Waiting for socket receive :-P"), _T("Waiting"), MB_OK);
closesocket(ConnectSocket);
return;
}
I had to know before I changed the way I answer socket questions here - I'm nuts like that
Cheers,
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Can you try calling WSAGetLastError after you receive the partial bytes? I'm curious if it is set to show the timeout. According to the documentation, recv should either read all or timeout. The docs do say:
Windows Sockets 2 does not define any standard blocking time-out mechanism for this function
I think we're hitting this case - the receive has timed out and who knows how the function is reporting the timeout. I think we can safely say the following:
For a blocking socket, you need to check the result from the recv and if you don't get the requested number of bytes, you have hit the timeout condition and need to handle it accordingly.
Judy
|
|
|
|
|
JudyL_FL wrote: Can you try calling WSAGetLastError after you receive the partial bytes?
Sure
WSAGetLastError() returns 0;
A long time ago, while writing some of my first communication code, I got bit by this (using pipes actually,
but it made me look at my sockets code) and it taught me to read the documentation thoroughly (which I
wasn't doing apparently ). That's when I found this:
"For connection-oriented sockets (type SOCK_STREAM for example), calling recv will return as much data
as is currently available—up to the size of the buffer specified."
FWIW, This also applies to pipes.
So, any amount of bytes returned by recv() indicates success. This can be seen especially when receiving
amounts larger than the socket buffer, where the protocol MUST return a buffer full of data to make room to
receive more.
This seems to be the number one thing overlooked by beginner socket programmers.
I studied MS's implementation of TCP a while back, and there is a timeout involved internally, but it's
not an error of any kind. I believe by default it's 200ms (that's the number that comes to mind) before
a recv() returns what it has currently buffered. That's what makes it inefficient to always request more
bytes than you're expecting.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Mark Salsbery wrote: WSAGetLastError() returns 0;
I was curious - it was easier to have you check since you had working code. How long does your recv sit before it returns? Never mind, it's not important. I vaguely remember some socket I did a looooong while back that (I think) waited a whole lot longer than your 200ms. Too far in the past to remember the details or if I had set a timeout value or it was using the built-in one. This may have been on CE, now that I think about it and that's a whole 'nother kettle of sockets. If it wasn't CE, it was long enough ago that it was at least as old as NT4.
I think we have our answer - always check the number of bytes received
Judy
|
|
|
|
|
JudyL_FL wrote: was curious - it was easier to have you check since you had working code.
I knew that hehe.
JudyL_FL wrote: How long does your recv sit before it returns?
About a second (accurate, huh?) from when I hit the OK button - that includes the 1000ms Sleep() in my fancy thread
synchronization.
I agree it doesn't matter - the internal "timeout" is implementation specific. Different protocol stack vendors are free to
implement the internals the way they want. That's why I only have MS specific info (and even that is vague now).
recv() API behavior, however, is well defined.
JudyL_FL wrote: I think we have our answer - always check the number of bytes received
Agreed!
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Mark Salsbery wrote: and it taught me to read the documentation thoroughly
BTW, I wasn't implying that you don't read the docs - I meant that was a turning
point for me, which is why I remember it vividly
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
no offense taken (especially since I quoted the docs a reply or so back), have a .... wait, where's the beer emoticon??? aaaargh
Judy
|
|
|
|
|
|
Right you are on both accounts - one recv will do if you know the packet size and the OP is not using a fixed size packet
|
|
|
|
|
I have encountered a weird namespace alias resolution bug(?) in VC++ 2003. I'm getting error C2653: 'innernamespace' : is not a class or namespace name for Orhun::Func2 (Commented out in the code provided below). Note that Func3, which is not a class method, with similar signature compiles just fine...
VC++ 2005 compiles all 3 functions without any errors.
Is this a known problem with 2003? My searches failed to return any meaningful results.
namespace topnamespace
{
namespace innernamespace
{
class Foo
{
public:
Foo() {}
Foo(int i) {}
};
}
}
namespace orh = topnamespace::innernamespace;
class Orhun
{
void Func1(orh::Foo e = topnamespace::innernamespace::Foo(-1))
{
}
};
void
Func3(orh::Foo e = orh::Foo(-1))
{}
Orhun Birsoy
|
|
|
|
|
It compiles fine on VS 2008 too.
Looks like a bug to me...I don't know if it's known or not though.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Hello, Orhun Birsoy.
I resolved the problem using "using namespace":
...
namespace orh = topnamespace::innernamespace;
using namespace topnamespace; // Added
class Orhun{
...
I guess, later versions of Visual Studio are equipped with the facility which do "using namespace" automatically for namespaces declared in same file.
But I consider its original to use "using namespace" for ur example. For example, we have a havit "using namespace std;" after "#include list or map".
**SnowFall**
-- modified at 22:45 Wednesday 14th November, 2007
|
|
|
|
|
I have to appoint an integer variable to another integer pointer itself. I tried this:
<br />
sNumber& DrawNumber()
{<br />
<br />
sNumber* pNum = new sNumber;<br />
pNum->i1 = edi1;<br />
pNum->i2 = edi2;<br />
<br />
}<br />
sNumber& sn = DrawNumber();<br />
for(int i=0; i<2; i++)<br />
{<br />
int x1 = sn.pNum[i]; <br />
int x2 = sn.pNum[i];<br />
}<br />
How much its right or wrong? have you got other any bookmarks on this topic? I have no possibility to compile this codes.
-- modified at 13:28 Wednesday 14th November, 2007
Was is das¿
|
|
|
|
|
I'm going to have to go with it is a lot wrong, but can't say where because I have no idea what you are asking.
|
|
|
|
|
Well abase... You are mean that it is impossible to appoint an integer variable to an integer pointer. Anyone can help me?
Was is das¿
|
|
|
|
|
Hakan Bulut wrote: it is impossible to appoint an integer variable
What does "appoint" mean? Are you in school? Did they teach you that word? It's wrong, it is not a standard term used in software development. You need to learn the proper terminology and use it for text based communications to succeed.
|
|
|
|
|
led mike wrote: What does "appoint" mean?
Right when I posted my first reply, I realized I forgot to ask that.
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Sorry, I could not remember what was mean it in computers literature.
Was is das¿
|
|
|
|
|
Hakan Bulut wrote: Sorry
how does that help?
Hakan Bulut wrote: I could not remember
Then go find out first so you can use the correct terms when posting questions.
|
|
|
|
|
Assingment.. I just to mean assing a variable to an integer pointer itself where in the sNumber structure and to objective oriented these elements to using easy?.. Have you got an idea OOP method?
Was is das¿
|
|
|
|
|
sNumber& DrawNumber() //pointer itself.
What does "pointer itself" mean? Your function returns a reference
{
sNumber* pNum = new sNumber;
pNum->i1 = edi1;
pNum->i2 = edi2;
You need to return a value from the function.
}
sNumber& sn = DrawNumber();
for(int i=0; i<2; i++)
The DrawNumber function (supposedly) returns a reference to a sNumber object.
How can you iterate through an array of two objects??
{
int x1 = sn.pNum[i];
int x2 = sn.pNum[i];
There's no such thing as "pNum" here.
}
Pretty much none of this makes sense
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Yeah how can i iterate thorough an array of two object. I just to mean that. So "sn" what has been refered to? What should i it to do? Can you help me?
"The DrawNumber function (supposedly) returns a reference to a sNumber object." I can see it. Anyway I asked this question myself. I don't asking about this function does returns a reference to a sNumber object. [I just ask how can i appoint an integer variable to an integer pointer sn referred object.?]
What do you say? it's no required?
-- modified at 13:52 Wednesday 14th November, 2007
Was is das¿
|
|
|
|
|
Hakan Bulut wrote: how can i iterate thorough an array of two object.
You need to have that array to begin with.
I'm not sure where to start here....this is really C/C++ fundamentals that I'm not sure if you know or not.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
A project which took 2.5 mins to compile is now taking more like 12 mins, and I've noticed that the PCH file is 22MB where it used to be 11MB. Could that be part of the slowdown? How much of an effect does the size of a PCH file have on compilation? Does it get loaded when each individual file is compiled or just once at the beginning? I'm being driven nuts waiting for it to compile when I've only made a small change to one header file!
TIA.
PS - it's about a 280kloc project in VC6.
|
|
|
|
|
delete it and start a clean + rebuild all. it's a known bug that its size a getting bigger and bigger sometimes.
|
|
|
|