|
In general the usual cause for that is that the listen/accept only occurs once.
Some reasons for that
- The processing is not threaded so the thread that is doing the accept is used to process or otherwise blocks.
- The accept must be restarted in some way (such as the windows async methods which must use Begin and End type methos appropriately.)
|
|
|
|
|
Well, in my case i got one server thread and one worker thread. Server thread first do all preparations, call listen and then call AcceptEx , and then just sleep. Every next call for AcceptEx occurs in worker thread, which processes everything. I am just wondering, how one worker thread can process everything? And more then one client? I am familiar with regular sockets, where you create a new thread for each accepted socket, but in this case i should just update my IO port with this newly created socket and worker thread will operate on every socket and every client connection?
011011010110000101100011011010000110100101101110
0110010101110011
|
|
|
|
|
I may not be following all your steps, but it appears all your threads end up waiting for socket accepts so everything is deadlocked.
Here's what I do...
Create a listener thread. Its job is to accept incoming connections and queue up the first completion job on the I/O completion port. I personally don't use AcceptEx anymore. I use a regular listener socket (bind()) and use an event (::WSAEventSelect(hListenSocket, hNetEvent, FD_ACCEPT);) to wake my listener thread when a connection request arrives. The listener thread proc just loops waiting on the event (and also a termination event for shutdown time). It looks like this:
DWORD CClientListener::ThreadProc()
{
while (1)
{
#define EVENT_NET 0
#define EVENT_TERMINATE 1
HANDLE Events[] =
{
hNetEvent,
hTerminateEvent
};
DWORD dwEventIndex = ::WaitForMultipleObjects(sizeof(Events) / sizeof(HANDLE),
Events, FALSE, INFINITE);
if (dwEventIndex == WAIT_FAILED)
{
break;
}
dwEventIndex -= WAIT_OBJECT_0;
if (dwEventIndex == EVENT_TERMINATE)
{
break;
}
if (dwEventIndex == EVENT_NET)
{
WSANETWORKEVENTS WsaNetworkEvents;
if (0 == ::WSAEnumNetworkEvents(hListenSocket, hNetEvent, &WsaNetworkEvents))
{
if (WsaNetworkEvents.lNetworkEvents & FD_ACCEPT)
{
OnAccept();
}
}
}
}
return 0U;
}
OnAccept()
1) creates a socket for the connection using ::WSAAccept()
2) creates an object of a class representing a client connection and adds this object to a collection
3) associates the new socket with the completion port using ::CreateIoCompletionPort()
4) creates/initializes a custom overlapped structure
5) Queues up a receive operation on the completion port using WSARecv()
That's it. I don't go to another thread to do the accept or anything else. From my OnAccept() call onward, the completion port threads handle all I/O.
For the I/O completion port I use a thread class. I create a pool of threads of this class, generally two threads per processor core works well. Pointers to these objects are kept in a collection so I can queue up a shutdown thread command for each pool thread on the completion port at shutdown time. The thread proc simply loops, waiting on ::GetQueuedCompletionStatus(), and handling each queued completion command, whether it be a receive, send, or exit thread command (determined by an opcode in the custom overlapped struct). I generally use a request-reply protocol (because it's easy, although I have added some unidirectional communication at times) so each processed receive command queues up a send command, and each processed send command queues up a receive command, all re-using the same custom overlapped struct.
Make sense?
Note: In case you didn't know...It's a common sockets programming mistake to assume the number of bytes requested to send or receive will all be sent or received in one call. This applies to I/O completion ports as well. Be prepared to handle sending or receiving remaining bytes when a completion event occurs. I personally track this in the custom overlapped struct.
Mark Salsbery
Microsoft MVP - Visual C++
modified on Monday, June 27, 2011 7:41 PM
|
|
|
|
|
Hey Mark, thanks for your reply - i was in fact doing almost same things :P. Well, but, thats it, and thank you so much!! I got rid of AcceptEx call, and, implemented accept event (like you do) and now it works!! Finally!
011011010110000101100011011010000110100101101110
0110010101110011
|
|
|
|
|
|
I am working with IOCP just for a 3 days now (current project requirement) and starting to love it. Completion ports are a way better then creating tons of threads for connections and tons of events as well - you got everything in one place, its like, kind of message loop, isnt it? having one struct, jumping from reading to writing and queuing stuff, defying operations, and performance for sure. Totally agree - IOCP is outstanding option - one port to rule them all Ok, back to coding
011011010110000101100011011010000110100101101110
0110010101110011
|
|
|
|
|
There are articles and even classes to tell how to dynamically move controls on forms.
I thought it should be a simple task to dynamically expand (MoveWindow) a control to fill available space under different user options, however, I cannot figure out how to dynamically determine the actual location of the new destination / size.
I have added an anchor button to get the location but I do not know how to dynamically get the location of this button.
I tried GetWindowRect , but that gives me location relative to the current window. GetClientRect gives me the actual size of the anchor button and that is no help either.
The “anchor button” is off the screen when the user selects the option and I use scroll to (up) bring it into view. Is is possible this is my problem and I need to recalculate the position after the scroll?
Still using VC6.0 and MFC, the app works for me, and no, updating to anything is not an option. Do not waste your and my time suggesting it.
Any constructive help will be as always appreciated.
Cheers
Vaclav
|
|
|
|
|
Using GetClientRect() on your main window will tell you how much space is available, so you can resize your control to those dimensions to get it to fill the space. Also, I'm not sure how to do it in MFC, but in Win32 the structure filled by the BeginPaint() call will also give you the dimensions of the visible part of your window; maybe part of the CDC class will help.
The best things in life are not things.
|
|
|
|
|
There's enough info in GetWindowRect(), see my answer... I'm sure CDC also has the information, since its the basis of drawing on the screen, but its not needed in this case.
|
|
|
|
|
You're correct, but I'm still not sure that I fully understand what the problem is.
The best things in life are not things.
|
|
|
|
|
He was just having problems getting the location of his anchor button on the screen to replace with one he was drawing out... but I think he realized his operations weren't all on what item he needed.
|
|
|
|
|
GetWindowRect() should work once you've converted coordinates using ScreenToClient() and assuming you've done the operation on the correct item.
For example, if you want the location of an anchor button:
CWnd *anchor = GetDlgItem(IDC_BUTTON);
RECT anchor_rect;
anchor->GetWindowRect(&anchor_rect);
ScreenToClient(&anchor_rect);
|
|
|
|
|
Thanks.
I was doing ScreenToClient on the wrong item!
Works as advertized.
Vaclav
|
|
|
|
|
Happens... glad you've got that all worked out... don't forget to vote!
|
|
|
|
|
Hi,
I am using visual studio 2008 MFC feature pack. My application has a "quick access toolbar" which is included in the MFC feature pack (it can be found at the top left of the main window. right next to the main menu).
My application is localized to several languages. Unfortunately, I can't find a way to translate the quick access toolbar and it's sub enries ("More Commands...", "Show Below the Ribbon" and "Minimize the Ribbon").
Does anyone know how to translate the quick access toolbar?
Thanks,
Kobi.
|
|
|
|
|
I am getting following error, where my program somehow using SetGUIDValue function.
Error 7 error C2664: 'A_StringFromGUID2' : cannot convert parameter 2 from 'OLECHAR [64]' to 'LPSTR' c:\program files\microsoft visual studio 9.0\vc\atlmfc\include\atlbase.h 5696
Regards
|
|
|
|
|
OLESTR's are unicode (ie, 16bits per character) and LPSTR is not-unicode (ie, 8bits per character).
So, I'm guessing you have a unicode / not-unicode problem.
Our usual cure here is to suggest people read the following article:
The Complete Guide to C++ Strings, Part I - Win32 Character Encodings[^]
Feel free to rate the article well if it helps you,
Iain.
I am one of "those foreigners coming over here and stealing our jobs". Yay me!
|
|
|
|
|
Hi!
I've shown a new Dialog On clicking a button in another Dialog using the following code:
CNewDialog *Ptr=new CNewDialog();
Ptr->Create(IDD_DIALOG1,this);
Ptr->ShowWindow(SW_SHOW);
My problem is When I click the first Dialog, Focus doesn't switch to the first Dialog.
I've to minimize the new Dialog, if I want to see the first Dialog. How to set Focus
to a Dialog while it is clicked or pressed ALT+TAB?
My first form is created like this:
UINT TransForm::ThreadExec1(LPVOID param)
{
DWORD result =0 ;
TerminateThread(Retry::ThreadExec, 0);
TerminateThread(TransForm::ThreadExec, 0) ;
IndForm ObjIndForm;
AfxGetApp()->m_pMainWnd = &ObjIndForm;
ObjPtrIndForm=&ObjIndForm;
glo_error=3;
ObjIndForm.DoModal();
return result;
}
However,I can't change the code for the two Dialog's creation.
modified on Monday, June 27, 2011 4:54 AM
|
|
|
|
|
I can see some problems:
1/ Unless you *really* know what you're doing it's a bad idea to create UI objects from multiple threads. It's like juggling with loaded guns whilst drunk. Sure, it may seem like a good idea at the time, but someone's gonna lose a toe.
2/ TerminateThread is also a really bad idea. I don't think I have *ever* used it. I've used plenty of Events, and BOOL's, and WaitForSingleMessage (hSomeThread, dwA_short_time)'s, but never TerminateThread.
That way memory leaks and crashes lie.
3/ To answer your actual question...
Ptr->SetFocus () ?
Iain.
I am one of "those foreigners coming over here and stealing our jobs". Yay me!
|
|
|
|
|
Iain Clarke, Warrior Programmer wrote: I can see some problems: 1/ Unless you *really* know what you're
doing it's a bad idea to create UI objects from multiple threads. It's like
juggling with loaded guns whilst drunk. Sure, it may seem like a good idea at
the time, but someone's gonna lose a toe. 2/ TerminateThread is
also a really bad idea. I don't think I have *ever* used it. I've used plenty of
Events, and BOOL's, and WaitForSingleMessage (hSomeThread, dwA_short_time)'s,
but never TerminateThread. That way memory leaks and crashes
lie. 3/ To answer your actual question... Ptr->SetFocus ()
? Iain.
Inside which Event?
|
|
|
|
|
You showed two pieces of code. Only one has "Ptr" in it. Look up SetFocus on msdn for more information on that member function. The name is a bit of a give away though.
The second piece of code you showed implied you have threads creating dialogs. My points about threads and TerminateThread applied to all windows programs, not just the bits you shows.
Just in case I misunderstood your question, when I used "Event" above, I meant Win32's event synchronisation objects, created by
CreateEvent win32 function.
If you've not heard of them (and mutexes [*], and semaphores) then you really should not be creating windows outside the main thread. I may sound harsh, but I simply mean you should not be using them *yet*. Do some reading, play with some programs, understand the ideas, then go wild.
Read
http://www.flounder.com/uithreads.htm[^] and have a browse through flounder's other articles. I don't agree with everything he says, but the vast majority of it is spot-on.
Iain.
[*] mutices?
I am one of "those foreigners coming over here and stealing our jobs". Yay me!
|
|
|
|
|
ObjIndForm.ShowWindow(SW_SHOW)
|
|
|
|
|
not working. Crashes at crtexec.c at the following code:
(HINSTANCE)&__ImageBase,
NULL,
lpszCommandLine,
StartupInfo.dwFlags & STARTF_USESHOWWINDOW
? StartupInfo.wShowWindow
: SW_SHOWDEFAULT
);
|
|
|
|
|
Here is the scenario
I have developed a custom class as below:
InsertEdit.h
class CInsertEdit :
public CWnd
{
DECLARE_DYNAMIC(CInsertEdit)
...
protected:
...
afx_msg void GetCustomerName();
afx_msg void GetInitialBalance();
afx_msg void GetPhoneNumber();
afx_msg void GetDateOfBirth();
afx_msg void GetCountry();
...
};
InsertEdit.cpp
#include "InsertEdit.h"
#define INSERTWINDOWCLASS L"INSERTWINDOWCLASS"
...
BEGIN_MESSAGE_MAP( CInsertEdit, CWnd)
ON_WM_CTLCOLOR()
ON_WM_CREATE()
ON_WM_PAINT()
ON_COMMAND(TEXT_2,GetCustomerName)
ON_COMMAND(TEXT_3,GetInitialBalance)
ON_COMMAND(TEXT_4,GetPhoneNumber)
ON_COMMAND(TEXT_5,GetDateOfBirth)
ON_COMMAND(TEXT_6,GetCountry)
END_MESSAGE_MAP()
IMPLEMENT_DYNAMIC(CInsertEdit, CWnd)
...
afx_msg void CInsertEdit::GetCustomerName()
{
wchar_t cst[256];
UserName.GetWindowTextW(cst,256);
MessageBox(cst,L"Test",MB_OK);
}
...
I am expecting that any type of command like "Click" or "key stroke" will call the GetCustomerName function called. but it is not.
CInsertEdit is a custom class with few edit class in it..
Am I missing anything?
Shall I have to add anything special on main Window class or anywhere else?
|
|
|
|
|
Looking at your code (and I am far from being an expert on MFC) the only time that function will be called is via the TEXT_2 command. How does this command get invoked?
The best things in life are not things.
|
|
|
|
|