|
Thanks.
So does that entitle having my cient send() send the amount of bytes as a primary transmission? That way the receiving end knows that it should expect X number of bytes before finishing?
Thanks again for the help Mark it goes a long ways!
|
|
|
|
|
That's up to you. You're responsible for keeping track of that so both
ends stay synchronized.
How you handle it defines your protocol.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Mark I hate to drag it on but I got to thinking. Why wouldnt TCP ensure a reliable delivery? I understand why UDP wouldnt but TCP has me a bit stumped. I just assumed it could be considered a reliable protocl.
It was my assumption that after TCP established a connection, through the method of acknowledgement replys from the receiver and the use of sequence numbers inherit to TCP that this wouldnt be a problem. I guess I got a little confused on this. Any clarification?
Also one final question! I have created a very basic wrapper class for my little console program but now I want to incorporate it into my chat GUI. I read somewhere that by turning one of the server's sockets to a WSAasyncsock or something of that nature that I could incorporate the recv into my windows message pump. The tutorial made it clear on how and where to setup my messags but was unclear as to which socket I need to make an windows based asyncronous socket, also won't the sender side have to send those windows messages as well? Otherwise at what point does my message pump just automatically know that data is coming in?
Did I make any sense there at all? =)
Mark your an excellent help! After this I promise I won't pester you any more!
Cliff
|
|
|
|
|
TCP is indeed reliable. The thing is, it's a stream oriented protocol, so it
only understands bytes. You could send 32KB-sized "packets" but the
underlying protocol may split that however it needs to for delivery. TCP
guarantees you'll receive all the bytes sent, in order, but they won't necessarily
come in one recv() call. That's why you need to do whatever it takes so the send
and receive ends stay in sync. It's essentially a protocol on top of TCP.
Make sense?
For the UI, yes, an asynchronous socket is ideal. Event-driven socket communication
is very efficient.
On the server side, you use the socket returned by accept(). That's the socket
connected to the client.
On the client side, you already have the socket - the one you connected to the server with.
I recommend reading the docs for WSAAsyncSelect VERY carefully.
The easiest way to get started is to request notifications for FD_READ and FD_CLOSE.
Then your window will receive the message you specify whenever there's data to be "recv()"'d
from the socket, and when the connection is closed.
On any given FD_READ notification, you can read as many bytes as you need to. If all the bytes
you're expecting aren't there yet, you need to keep track of that for when you get the next FD_READ.
If more bytes than you recv() are available, you're guaranteed to get another notification.
Again....read the docs carefully
Beaon wrote: also won't the sender side have to send those windows messages as well?
No. Both ends of the connection handle everything themselves. Basically, just
sending and receiving bytes. The notifications are available so you don't have to
sit in a loop wasting CPU cycles waiting for data.
Once a connection is established, there's no difference between the client and the server ends.
You could actually use identical code on both ends.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Your awesome buddy. Thanks alot, time to go play in some code! =)
|
|
|
|
|
Alrighty sir, I swear I wouldnt be asking if I could find the answer somewhere in a tutorial but so far no luck.
Everywhere I read says that in order to make these sockets compatible with my GUI I need to have an async socket.
I understand that, my problem is where exactly do I put the WSAAsyncSelect command?
I have tried both places.
Create Listenign Socket
Bind Listening SOcket
Listen Listening SOcket
Create Client Socket
WSAAsyncSelect(Client Socket) //Ive tried it here
Client SOcket = accept (Listening Socket)
//WSAAsyncSelect(Client Socket) //And I have tried it here.
If I try it higher up before I make the accept call, that place seems the most logical to me because it is the accept call that locks up the gui right? However when I do it the GUI locks up. If I telnet to my port, or use my little console program I made and connect to that port the GUI unfreezes and a connection is established as normal. If I try to send data nothing is received on my GUI end.
If I place the WSAAsyncSelect after the Accept command same thing. Client GUI hangs untill a connection is established. Once its established everything works however, I can even send text messages from my console program and it will output correctly on my GUI's interface.
I am guessing that I am assigning the correct socket into async mode and my windows messages are working and everything, but why would it still be locking up waiting for a connect? Perhaps I am missing something still!
I spent the last hour poken around MSDN libs and other sites and havnt been able to get a simple and descent example. Thanks again Mark, especially for your patience!
Cliff
|
|
|
|
|
Hi Cliff,
I forgot to mention....
The listening socket is separate. Once it is placed in a listening state, that's
all it does. For that socket, you'd want to use the FD_ACCEPT flag to get a window message
when a client tries to connect.
The WSAAsyncSelect() calls can be made any time after the sockets are created.
Generally, it's done something like this....
For the listening socket, call WSAAsyncSelect(...FD_ACCEPT) after you call listen(), then
return to your GUI or whatever. When you get a message indicating FD_ACcept to your
window, THEN call accept().
For the client end of the connection, call WSAAsyncSelect(...FD_CONNECT) right after you
create the socket. Then set the socket to non-blocking mode using ioctlsocket(), something like:
DWORD dwNonBlockingMode = 1;
::ioctlsocket(hSocket, FIONBIO, &dwNonBlockingMode);
Call connect() on the socket and return to the GUI - your window will receive the message when
connection is complete. When you receive the connect completion message, call
WSAAsyncSelect(...FD_READ|FD_CLOSE) on the socket to start receive and close notifications.
For the server end of the connection, when you receive an accept notification,
call accept() to create the connection socket.
Set this socket to non-blocking mode using ioctlsocket() as shown above,
then call WSAAsyncSelect(...FD_READ|FD_CLOSE) to start receive and close
notifications.
Make sense?
Mark
*EDIT* I crossed out the parts about setting the sockets to non-blocking.
Calling WSAAsyncSelct() does this for you
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
It sure does. Thanks again! I got today off so as soon as I get home I will be working on this!
Thanks for everything! =)
|
|
|
|
|
Hey check this out, It works!
Mark your the man!
Thanks for all the help buddy!
I'm so excited. Now I am going to learn how to make my app look prettier then the default windows stuff.
Lots of learning to do!!! =)
Cliff
Cliff
|
|
|
|
|
Kewl! No problemo.
Have fun,
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Hi,
I am trying to display non-english text on the std console. I have tried various methods like
setconsole, _wsetconsole etc.. Defined _UNICODE and UNICODE macros also used wstring, wcout thinking that wide char variant might print the non-english text. Below is my sample program
#include <iosstream>
#include <locale>
using namespace std;
int_tmain()
{
wstring nonEnglishName = _TEXT("槧雲鼻");
wcout.imbue(locale("jpn");
wcout << _TEXT("Name in japanese is = ") << nonEnglishName.c_str() << endl;
return 0;
}
The output I am getting is = Name in japanese is = ₧▀ë_ò@
My system locate is still set to US_ENGLSH and I do not want to change it.
Can anybody please guide me regarding the correct procedure for displaying non-english text on the console?
Thanks
-- modified at 13:46 Wednesday 12th September, 2007
|
|
|
|
|
Check out the SetConsoleCP and GetConsoleCP API functions.
Nothing is exactly what it seems but everything with seems can be unpicked.
|
|
|
|
|
I have a application that does some computations based on inputs from user, prints the results of the calcutaions in a file and exits. I am using ExitProcess() for exiting from the application. But while closing the application I get a error "The instruction at "0x73e6827a" referenced at "0x00157479c". The memory could not be read" .
When I use TerminateProcess() I dont get the error message eventhough TerminateProcess() is not a recommeneded method for exiting process. Why does this happen?
|
|
|
|
|
What happens if you send WM_CLOSE to that program?
|
|
|
|
|
Is it a console app or a GUI app?
You shouldn't have to call ExitProcess and definitely shouldn't have to use TerminateProcess.
Some info: Terminating a Process[^]
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
The difference b/w ExitProcess and TerminateProcess is ExitProcess will send DETACH message to all the loaded dll where TerminateProcess won't. So the error may occured on unloading some dll loaded by ur application.
AJay
|
|
|
|
|
Hi guys,
I´m not sure I am using the corect terminology, since I´m pretty new to MFC programming. Sorry for that.
I created an object of a wrapper-class from an OCX libray (included with class _myObjectClass : public COleDispatchDriver ).
As opposed to other classes in this library and what "OCX" suggests, this one is non-visual (no ActiveX).
I can use this object in a function just fine, except for when calling the function from a thread.
This works fine:
<br />
void TestDlg::DoIt()<br />
{<br />
_myObject m_obj;<br />
<br />
m_obj.CreateDispatch("xxxx.xxxx");<br />
<br />
m_obj.ObjMethod(xxx);<br />
}<br />
<br />
<br />
void TestDlg::OnButton()<br />
{<br />
DoIt();<br />
}<br />
But this does not
<br />
static UINT MyThread(LPVOID p);<br />
<br />
UINT TestDlg::MyThread(LPVOID p)<br />
{<br />
TestDlg * app=(TestDlg *) p;<br />
<br />
app->DoIt();<br />
<br />
return 0;<br />
}<br />
<br />
void TestDlg::DoIt()<br />
{<br />
_myObject m_obj;<br />
<br />
m_obj.CreateDispatch("xxxx.xxxx");<br />
<br />
m_obj.ObjMethod(xxx);<br />
}<br />
<br />
void TestDlg::OnButton()<br />
{<br />
AfxBeginThread(MyThread, this);<br />
}<br />
Can anyone explain that behaviour or even suggest a solution?
Any advice or idea is greatly appreciated.
Thanks in advance,
..kyer
|
|
|
|
|
Verwenden Sie bitte PostMessage() anstatt thread.
Try using PostMessage to send a message to your dialog rather than calling the public function from a thread. You should always try to avoid executing functions in a dialog from an external thread.
Best Wishes,
-Randor
|
|
|
|
|
Thanks a lot for your advice.
I implemented it and it works. But now my dialogue is blocked while the function is executed. It does not run as a second thread anymore, which is my goal.
Do you have any other suggestions?
Kind regards,
..kyer
|
|
|
|
|
Why can't you just move all of the COM instantiation and function calls into the thread?
Also if you are accessing/writing to a variable visible to more than one thread, you will need to protect that variable with a critical section or other thread synchronization object. In other words, if variable N is readable/writable to both threads A and B then you will need to protect this variable. A simple CriticalSection object should be sufficient.
It is 1800 here in Norway/Norwegen and I am leaving the office for the day, but there are many articles here on Codeproject which address the issues with regards to multithreading your application and synchronizing access to variables.
Good luck!
-Randor
|
|
|
|
|
Randor,
many thanks for your help. I´ll try and see what I can learn about COM instantiation.
Kind regards,
..kyer
|
|
|
|
|
Solution:
You have to call CoInitalize to initialize the library in the thread and UnInitialize to close it.
Like this:
<br />
void TestDlg::DoIt()<br />
{<br />
CoInitialize(NULL);<br />
<br />
_myObject m_obj;<br />
<br />
m_obj.CreateDispatch("xxxx.xxxx");<br />
<br />
m_obj.ObjMethod(xxx);<br />
<br />
CoUninitialize();<br />
}
|
|
|
|
|
Hello all,
Now I writing about TTS program. I already got the TTS function from the Microsoft word.
but Now I effort to write for MS Excel. The following is a piece of code of MSWord.
CMSWordSpy::CMSWordSpy()
: m_nStart(-1)
, m_nEnd(-1)
, m_bstrText(_T(""))
, m_pApp(NULL)
, m_pWindow(NULL)
, m_pRangeReplace(NULL)
, m_pRangeOrg(NULL)
, m_pScanRange(NULL)
, m_bWordIsRunning(false)
, m_hwnd(NULL)
, m_hwndRef(NULL)
{}
CMSWordSpy::~CMSWordSpy()
{}
void CMSWordSpy::dump_com_error(_com_error &e)
{
/*
_bstr_t bstrSource(e.Source());
_bstr_t bstrDescription(e.Description());
CString s;
s.Format(_T("code=%08lx, meaning=%s, Source=%s, Description = %s"),
e.Error(),
e.ErrorMessage(),
(LPCTSTR) bstrSource,
(LPCTSTR) bstrDescription);
LOG(s);
TRACE(s);
*/
}
void CMSWordSpy::Connect(BOOL bNewDoc, BOOL bMaximize)
{
if (m_bWordIsRunning)
return;
try
{
if (SUCCEEDED(m_pApp.GetActiveObject(L"Word.Application")))
{
TTS.Speak(_T("Key stone is connecting to Microsoft Word."),
_T("Windows"), LH_MODESENTENCE, -1, -1, TRUE);
if (bMaximize)
m_pApp->WindowState = wdWindowStateMaximize;
if (bNewDoc)
{
DocumentsPtr pDocs = m_pApp->Documents;
pDocs->Add();
}
m_bWordIsRunning = true;
}
}
catch (_com_error &e)
{
dump_com_error(e);
}
}
void CMSWordSpy::Disconnect()
{
if (m_bWordIsRunning)
{
try
{
TTS.Speak(_T("Key stone is disconnecting from Microsoft Word"),
_T("Windows"), LH_MODESENTENCE, -1, -1, TRUE);
// Setting smart pointers to NULL automatically
// handles any necessary release.
m_pWindow = NULL;
m_pRangeReplace = NULL;
m_pRangeOrg = NULL;
m_pScanRange = NULL;
m_pApp = NULL;
}
catch (_com_error &e)
{
dump_com_error(e);
}
}
m_bWordIsRunning = false;
}
but now i got the error in msword.tlh file. that's file is auto generate file.
<b>error is C2011 'enum redefinition'</b>
is anyone help me for that problem ?
Thanks,
tun
|
|
|
|
|
tunminhein wrote: error is C2011 'enum redefinition'
What does your code snippet have to do with this error?
"A good athlete is the result of a good and worthy opponent." - David Crow
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|
Hello,
is there something what i have to change in my project settings if i want to
compile on dual core cpu, maybe in Linker options or something else??
Sorry, but i never work before with dual core!
Thank you in advance!
termal
|
|
|
|