|
Hi,
I'm writing a server application using UDP and the I/O Completion port. I red some articles and i know the things about it.
My application scans a list of servers, requests some information, unpacks the information and stores the information, this is a process in loop. However, after a while i get the 10055 Error or better said WSANOBUFS. Now i red that that means that there cant be made any more locks ( source[^] ) I cant quit seem to find where the error takes place, there might be a sort of loop in locking where the the unlock never hits, but i dont know where that would be then. Is there any way to detect a possible deadlock? or do you know something else that might be wrong? Thanks already
-Koen
|
|
|
|
|
Where are you getting the WSAENOBUFS error? On a send, receive, connect?
If on a send, have you disabled send buffering for the socket?
Are you using IOCP for sends, recvs, connects? All overlapped operations?
|
|
|
|
|
int res = WSARecvFrom(m_sSocket, &m_wsaBuf, 1, reinterpret_cast<LPDWORD>(&buflen), &temp, reinterpret_cast<sockaddr*>(&m_objAddress), &sockaddr_len, &m_objOverlapped, NULL);
There i get the error 10055, Sending goes just fine.
Since im using UDP im not connecting. Next to that, i dont use overlapped operations everywhere, i got a mysql class wich just sends a status update every 10 seconds, and a remote manager class wich uses TCP. both the mysql and the rmanager are using normal winsock so without overlapped operations.
<br />
m_sSocket = socket(AF_INET, SOCK_DGRAM, 0);<br />
m_objAddress.sin_family = AF_INET;<br />
m_objLocalAddress.sin_family = AF_INET; <br />
m_objLocalAddress.sin_addr.s_addr = htonl(INADDR_ANY);<br />
m_objLocalAddress.sin_port = 0; <br />
m_hIOCP = hIOCP;<br />
if (bind(m_sSocket, reinterpret_cast<sockaddr*>(&m_objLocalAddress), sizeof(m_objLocalAddress))==SOCKET_ERROR){<br />
TRACE("Error binding localaddress with the socket, Error: %i\n", WSAGetLastError());<br />
}<br />
if (CreateIoCompletionPort(reinterpret_cast<HANDLE>(m_sSocket), hIOCP, reinterpret_cast<DWORD>(const_cast<CVirtualSession*>(this)), 0)==NULL){
TRACE("Error binding Session to the main object, Error: %i\n", WSAGetLastError());<br />
return;<br />
}
Here i initialize is UDP session, there are like 400 udp virtual sessions continiously sending and recieving data. the first minut it goes all well, but after that, every sessions returns the error 10055 on recieving
|
|
|
|
|
This may or may not be the problem, but based on what I've seen it's the first thing that comes
to mind. I hope this helps a bit...
Unless you always keep enough receive buffers queued in your IOCP then the socket can receive
datagrams faster than you are pulling them out of its buffer.
If the socket is not "connected" (for UDP that just means all datagrams will be ignored except
from the "connected" address) then the socket's recv buffer gets filled with every UDP datagram it
sees on the network. You need to pull them out fast enough to keep enough buffer space for
receives.
One option is to use a connected socket to receive UDP datagrams on. The drawback is you'd need
400 sockets, or one for every session as you described.
Another option is to always have a pool of overlapped WSARecvFrom() calls pushed on the IOCP
stack so there will always be one available when a datagram is received. You could use the
FD_READ notification to help notify a thread that data has been received on the socket and make
sure there's a pending overlapped receive operation ready to accept the data.
Also make sure your IOCP is properly "tuned" with the right amount of threads in the pool to
most efficiently handle all the received datagrams.
These articles may be helpful too (you may have seen them already - I keep them bookmarked for
any IOCP troubles I encounter )...
Windows Sockets 2.0: Write Scalable Winsock Apps Using Completion Ports[^]
INFO: Design Issues When Using IOCP in a Winsock Server[^]
|
|
|
|
|
thanks, i havent solved the problem yet however i didnt try your possible solutions so
I'll working on it as soon as my job ends. i'll tell you how it goes as soon as there's some result. thanks again
|
|
|
|
|
If the socket is not "connected" (for UDP that just means all datagrams will be ignored except
from the "connected" address) then the socket's recv buffer gets filled with every UDP datagram it
sees on the network. You need to pull them out fast enough to keep enough buffer space for
receives.
I tried some solutions but i cant seem to get them working. Its probably my lack of experiance but well,
The fundamental code:
<br />
while (1){ <br />
BOOL bIORet = GetQueuedCompletionStatus (
pThis->m_hIOCompiltionPort,<br />
&dwIoSize,<br />
reinterpret_cast<LPDWORD>(pThis),<br />
&ptrOverlapped, INFINITE);<br />
if (!bIORet){<br />
TRACE("Winsock error code: %i\n", GetLastError());<br />
Gameye::Library::Thread::CMPThread::Sleep(0);<br />
}<br />
else{<br />
ptrSession = static_cast<CVirtualSession*>(ptrOverlapped->Pointer);<br />
CAbstractServerClass* ptrGameClass = (*pThis->m_ptrGameManager)[ptrSession->getNDServer()->GameID];<br />
if (ptrGameClass == NULL){<br />
TRACE("Game is unknown, probably removed\n");<br />
}<br />
else{<br />
objToolset.Session = ptrSession;<br />
switch(ptrSession->getTask()){<br />
case RequestSend:
if (WSASendTo(sSocket, <br />
ptrSession->getWSABuffer(),<br />
1,<br />
reinterpret_cast<LPDWORD>(&ptrSession->getWSABuffer()->len),<br />
0,reinterpret_cast<sockaddr*>(ptrSession->getAddress()),<br />
sizeof(sockaddr_in),<br />
ptrSession->getOverlapped(), NULL) == -1)<br />
{<br />
int iErrorCode = WSAGetLastError();<br />
if (iErrorCode != 997){
TRACE("Sending failed because: %i\n", WSAGetLastError());<br />
break;<br />
}<br />
}<br />
ptrSession->setStatus(AfterSend);<br />
break;<br />
case RequestRecieve:
if (WSARecvFrom(sSocket, <br />
ptrSession->getWSABuffer(),<br />
1,<br />
reinterpret_cast<LPDWORD>(&ptrSession->getWSABuffer()->len),<br />
&iTemp,reinterpret_cast<sockaddr*>(ptrSession->getAddress()),<br />
&iSockAddrSize,<br />
ptrSession->getOverlapped(), NULL) == -1)<br />
{<br />
int iErrorCode = WSAGetLastError();<br />
if (iErrorCode != 997){
TRACE("Recieving failed because: %i\n", WSAGetLastError());<br />
ptrSession->setStatus(AfterRecieve);<br />
}<br />
}<br />
ptrSession->setStatus(AfterRecieve);<br />
break; <br />
case AfterSend:
ptrSession->incSendBytes(dwIoSize);<br />
ptrGameClass->RetrieveServerInfo(ptrSession->getNDServer(), &objToolset);<br />
break;<br />
case AfterRecieve:
ptrSession->incRecvBytes(dwIoSize);<br />
if (ptrGameClass->UnpackServerInfo(ptrSession->getNDServer(), &objToolset) == 0){
ptrSession->Finish();<br />
}<br />
break;<br />
case Finishing:<br />
pThis->m_objSql.AddGame(ptrSession->getNDServer());<br />
break;<br />
default:<br />
break;
}<br />
}<br />
}
Most calls should be clear. the events i call are simpel functions, they should return in a inch of a sec, next to that, i can have 10 workerthreads running and still i get the same error. some sessions come out alive but most of them just gives the known error on recieve. You also see that after every send, a call to WSARecvFrom is been made. its not directly but again with the inch of a second.
Also, with 10 sessions, 2/3 sessions returns the error on recieve the rest just works fine. with 400 sessions, a few return with the error and a few dont. that indicates that the recieve buffer aint full right?
|
|
|
|
|
You get a completion packet indicating "RequestRecieve" and in response you call WSARecvFrom()
before calling ptrSession->setStatus(AfterRecieve);
Chances are pretty good that another thread has already processed the completion of the
WSARecvFrom() call before you can even check the error code!
So, you'll get ANOTHER RequestRecieve before you have a chance to set the session status to
AfterRecieve.
Make sense?
In other words, you probably want to call ptrSession->setStatus(AfterRecieve) BEFORE you call
WSARecvFrom().
Also, use WSA_IO_PENDING instead of 997 so I can read your code haha I don't have all the WSAE
codes memorized yet
|
|
|
|
|
Nope, that aint the proble. would be really quick
and srry about the code, its just a test project. when i got it all working i'm gonna merch it and mostly rewrite it.
Thanks anyway
|
|
|
|
|
hi,
I can't seem to create a simple c++ console application in VStudio .NET 2003. Whenever I create the console application provided in the template projects, I can't compile with for example, the system function cout
What could I be doing wrong?
If this can't be fixed, is there going to be a problem if I install both VStudio6.0 and VStudio.NET 2003 in the same machine/OS?
Thank you and Happy New Year
I'm a SysAdmin, I battle my own daemons.
|
|
|
|
|
Don't forget to include the iostream header file.
#include <iostream>
Darka [ Xanya]
"I am not a slave to a god that doesn't exist."
|
|
|
|
|
Thanks but I have done that. Besides it already includes "stdafx.h"
|
|
|
|
|
|
i thought the problem was being caused by the new vstudio .net (i am new to .net)
anyhow, this helped... thanks!
|
|
|
|
|
Hi
Why after this piece of code value of d is : 3.4560000896454 ?
float f = (float)3.456;<br />
double d = (double)f;
Thanks
|
|
|
|
|
In computers, real values are only approximations; there are only a limited number of bits used to represent fractional values. You need to keep that in mind when dealing with float and double type values. The double type includes a larger number of bits (64 in the Windows world) than the float type (32).
When you do the conversion from one to the other via the (double) cast operator, those extra bits come into play. In a float value, 3.456 may have a string representation of 3.456000. A double version of that value adds additional significant digits, which results in the 3.456000089454 that you are seeing.
Software Zen: delete this;
|
|
|
|
|
Hi,
I have a base class(lets say class X) which is a "friend" of another class(lets say Class Y).
Using the base class(class X) I can access private members in the other class.
My problem is that I derived a new class(class Z) from the base class,and I need to use a private method from class Y.
I thought that if class X is a friend of class Y , then all the derived classes of class X are also friend of class Y , but I realized that I was wrong.
My problem is that I can't modify class X and class Y because it is our core.
anyone?
With best regards,
Eli
|
|
|
|
|
declare the friend as protected
|
|
|
|
|
I've made an SDI Appl with DB Support by MFC Wizard. now in an ADmin module i validat the password supplied by the Administrator and open a Modal Dlg Box with certain Edit Text fields radio buttons.
I've 4 buttons in it.
1) Add
2) Inventory
3) Edit
4) Exit.
On addition i want to add the values in these fields to the DB. but i'm not able to add the member variables to m_pSet-><Field_Name> values to that of the edit text boxes. also I ve a field as accession number(1111-9999) which is a p_key. while we add an item the greatest acc. no. has to be read n a next gr8er no needs to be gen. associated with the item.
The basic prob is how to update data without closing the Dlg Box.
I know this is a lengthy one...plz bear with it.
Success makes life easier. It doesn't make living easier.
SH UVIK
|
|
|
|
|
|
No i cant let a user access the SDI window when he/she is accessing the Dlg Box.
I just used DDX but still until the Modal Dlg Box Closes I'm not able to invoke update to DB.
how to do it
Success makes life easier. It doesn't make living easier.
SH UVIK
|
|
|
|
|
shouvik.d wrote: No i cant let a user access the SDI window when he/she is accessing the Dlg Box.
Disable the SDI window while the dialog box is active. MFC simulates modal dialog boxes exactly in this way, creating a modeless dialog box from template, disabling main window if any, display the dialog, and reenable the main window after.
Another possibility is to inform application from the modal dialog to perform the update.
This way you don't have to wait the dialog to close, such as in
void CDlg::OnButtonClicked()
{
CData data;
static_cast<CSDIApp *>(AfxGetApp())->updateDatabase(&data);
}
and
void CSDIApp::updateDatabase(CData *pData)
{
}
|
|
|
|
|
firstly thr is no CData class only CDatabase is available.
and plz can u throw a bit more light into this. I'm an amateur n very new to VC++.
There are only two kinds of people who are really fascinating-people who know absolutely everything, and people who know absolutely nothing.
Oscar Wilde (1854-1900)
SH UVIK
|
|
|
|
|
I mean CData as a placeholder for your data, you should implement it yourself as a mean to communicate between the dialog and the application object. In this way, you can collect data from the dialog, declare and fill a structure or class (this is CData) and pass it to the application (or whatever other object you want to delegate for operating in database).
|
|
|
|
|
This is what when the admin module has to be invoked. A passsword validation is done. Later the Admin window opens.
void CLibManView::OnAdmin()
{
Pass p1;
p1.DoModal();
CString str,query,str1;
int flag = 0;
str=p1.m_pass;
m_pSet->Close();
query = "Select * from Password where User='Admin'";
m_pSet->Open(CRecordset::dynaset, (LPCTSTR)query,CRecordset::none);
m_pSet->MoveFirst();
while(!m_pSet->IsEOF())
{
str1=m_pSet->m_Pass;
if(str1==str)
{
flag=1;
break;
}
m_pSet->MoveNext();
}
if(0==flag)
MessageBox("Wrong Password");
else
{
ad.DoModal();
m_pSet->Close();
char temp[2];
itoa(ad.type,temp,2);
char locstat[2];
itoa(2,locstat,2);
query="insert into book values('"+ad.m_Auto_Ac_No+"','"+ad.m_Add_Name+"','"+ad.m_Add_Auth+"',"+temp+","+ad.m_Add_Price+",'"+ad.m_Add_Date+"',"+locstat+")";
m_pSet->Open(CRecordset::dynaset,(LPCTSTR)query,CRecordset::none);
m_pSet->Update();
m_pSet->Close();
}
}
So without closing the Admin dlg box how to update data. also i'm getting an error.
Syntax error in FROM clause on the above query.
plz help
Man can acquire accomplishments or he can become an animal, whichever he wants. God makes the animals, man makes himself.
G. C. Lichtenberg (1742-99), German physicist, philosopher.
SH UVIK
|
|
|
|
|
One method is to do what Cristian Amarie said above. Another is to move the SQL code into the dialog itself.
You may be right I may be crazy -- Billy Joel --
Within you lies the power for good, use it!!!
|
|
|
|
|