i try to built socket aplication in thread . usually i did not get error in my aplication when i implemented accept() function. but in these code i got error.
Code:
void CComputer::OnButtonStart()
{
// TODO: Add your control notification handler code here
WSADATA wsd;
CString str, m_sError;
int iSize;
CString status;
CWaitCursor wait;
UpdateData(TRUE);
for (int i=0; i<40; i++ )
sClient[i] = NULL;
//cek port input
if(m_sPort.IsEmpty())
{
AfxMessageBox("Please Insert Port Number...!!");
m_cStartBtn.EnableWindow(TRUE);
return;
}
// cek winsock2
if (WSAStartup(MAKEWORD(2,2), &wsd) !=0)
{
AfxMessageBox("Failed to Load Winsock....!!");
return;
}
// inisialisasi soket dan port
sServer=socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (sServer ==SOCKET_ERROR)
{
m_sError.Format("socket() failed : %d ", WSAGetLastError());
AfxMessageBox(m_sError);
return;
}
//port
sadd_Server.sin_family = AF_INET;
sadd_Server.sin_port = htons(atoi(m_sPort));
sadd_Server.sin_addr.s_addr = htonl (INADDR_ANY);
iSize = sizeof(sadd_Server);
int opt,reuse;
reuse = setsockopt(sServer, SOL_SOCKET, SO_REUSEADDR, (char *) &opt, sizeof (opt));
if (reuse == SOCKET_ERROR)
{
//close(); // close.
m_sError.Format("failed reuse socket : %d ", WSAGetLastError());
return;
}
// bind : mengikat antara aplikasi dengan port yang dibuat
if(bind(sServer, (struct sockaddr *)&sadd_Server, iSize) == SOCKET_ERROR)
{
m_sError.Format("bind() failed : %d " , WSAGetLastError());
AfxMessageBox(m_sError);
return;
}
nClients=0;
// status.Format(" running");
m_sStatus.SetWindowText("running");
//refresh database
SetTimer(1,1000,NULL);
//listen port dengan backlog maksimum
listen(sServer,SOMAXCONN);
m_cStartBtn.EnableWindow(FALSE);
m_cStopBtn.EnableWindow(TRUE);
//looping, dengan menggunakan thread
AfxBeginThread(&thread,0);
}
UINT thread(LPVOID p)
{
int iSize;
int s=1,msgcount,loop=1,flag=0;
CString data, data_send;
CComputer *dlg=(CComputer*)AfxGetApp()->GetMainWnd();
msgcount=dlg->nClients;
iSize=sizeof(dlg->sadd_Client);
dlg->sClient[msgcount]=accept(dlg->sServer,(struct sockaddr *)&(dlg->sadd_Client),&iSize);
if (dlg->sClient[msgcount]==INVALID_SOCKET)
{
AfxMessageBox("Error : invalid socket");
dlg->m_cStartBtn.EnableWindow(TRUE);
return 0;
}else
{
AfxMessageBox(" socket is ready");
dlg->m_cStartBtn.EnableWindow(TRUE);
}
return 0;
}
when i run my aplication, i got messagebox "Error : invalid socket". from that messagebox we know that my accept() function got error.
any suggestin how to correct it?? what should i do??
Try calling WSAGetLastError() to see what the error code is. Other than that, you should NOT be doing any GUI manipulation within a thread, but that topic is more appropriate in the multithreading forum.
Looks fishy. Are you sure that the main window is the CComputer dialog? Check with the debugger. Check the value of sServer before calling the thread, then check it when the thread starts (after the cast to CComputer *).
AfxGetApp is not the way to get info in the thread. You should pass it to the thread as part of its parameter. AfxGetApp returns a CWnd in the main GUI thread of your app. Worker threads should not be calling members in the GUI thread.
Then you can be sure you have a pointer to the CComputer class and should be able to access the member variables.
However, why not do the whole socket stuff inside your thread? You could avoid the interaction of the class with the thread and do all the work on the sockets inside the thread.
Then you can be sure you have a pointer to the CComputer class and should be able to access the member variables.
I think those my problem before. i got difficult how to acces variable in my aplication. my script at line like " CComputer *dlg=(CComputer*)AfxGetApp()->GetMainWnd()" did not work correctly.
why not do the whole socket stuff inside your thread?
i am not really understand about socket + thread, so i just do what i have learned before. would you like to teach me about this problem?? thanks..
i am not really understand about socket + thread, so i just do what i have learned before. would you like to teach me about this problem?? thanks..
Well, the OnButtonStart does not do much more than check if the port is empty, then create the socket, bind it and set it to listen mode. The thread does nothing more than accept an incoming connection, add it to some management data and terminates.
You could move the creation of the socket from OnButtonStart to the thread and handle the incoming connection there (at the moment, you can only accept one single connection). If you need the management data inside the CComputer class, you can still pass the this-pointer (or better, a window handle) to the thread and let the thread post messages to the dialog whenever a new connection is established. If you want to be able to accept more than one connection, you need to wrap a loop around your "accept" part inside the thread.
it did not solve my problem. i still can not acces variable socket in OnButtonStart()
Originally Posted by Richard.J
Well, the OnButtonStart does not do much more than check if the port is empty, then create the socket, bind it and set it to listen mode. The thread does nothing more than accept an incoming connection, add it to some management data and terminates.
You could move the creation of the socket from OnButtonStart to the thread and handle the incoming connection there (at the moment, you can only accept one single connection). If you need the management data inside the CComputer class, you can still pass the this-pointer (or better, a window handle) to the thread and let the thread post messages to the dialog whenever a new connection is established. If you want to be able to accept more than one connection, you need to wrap a loop around your "accept" part inside the thread.
Does that help?
that help me. but i still don't really understand if without example. would you like to give it??
how about pointer "this " like you said before?? i still can not use that to acces variable value...
1. taking your code and modifying it only slightly should work:
Code:
void CComputer::OnButtonStart()
{
...
//looping, dengan menggunakan thread
AfxBeginThread(&thread,this);
}
UINT thread(LPVOID p)
{
int iSize;
int s=1,msgcount,loop=1,flag=0;
CString data, data_send;
CComputer *dlg=reinterpret_cast<CComputer*>(p);
...
}
Please note that I replaced your cast instruction by the reinterpret_cast because that is more C++ like.
So, provided that your Dialog is still "alive", i. e. it is not destroyed, your thread should be able to access the variables. But if you close the dialog right after OnButtonStart exits, your thread might access invalid data.
2. Moving the code you already have would yield this:
Code:
void CComputer::OnButtonStart()
{
// TODO: Add your control notification handler code here
WSADATA wsd;
CString str, m_sError;
int iSize;
CString status;
CWaitCursor wait;
UpdateData(TRUE);
for (int i=0; i<40; i++ )
sClient[i] = NULL;
//cek port input
if(m_sPort.IsEmpty())
{
AfxMessageBox("Please Insert Port Number...!!");
m_cStartBtn.EnableWindow(TRUE);
return;
}
nClients=0;
// status.Format(" running");
m_sStatus.SetWindowText("running");
//refresh database
SetTimer(1,1000,NULL);
m_cStartBtn.EnableWindow(FALSE);
m_cStopBtn.EnableWindow(TRUE);
//looping, dengan menggunakan thread
AfxBeginThread(&thread,this);
}
UINT thread(LPVOID p)
{
int iSize;
int s=1,msgcount,loop=1,flag=0;
CString data, data_send;
// cek winsock2
if (WSAStartup(MAKEWORD(2,2), &wsd) !=0)
{
AfxMessageBox("Failed to Load Winsock....!!");
return;
}
// inisialisasi soket dan port
sServer=socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (sServer ==SOCKET_ERROR)
{
m_sError.Format("socket() failed : %d ", WSAGetLastError());
AfxMessageBox(m_sError);
return;
}
//port
sadd_Server.sin_family = AF_INET;
sadd_Server.sin_port = htons(atoi(m_sPort));
sadd_Server.sin_addr.s_addr = htonl (INADDR_ANY);
iSize = sizeof(sadd_Server);
int opt,reuse;
reuse = setsockopt(sServer, SOL_SOCKET, SO_REUSEADDR, (char *) &opt, sizeof (opt));
if (reuse == SOCKET_ERROR)
{
//close(); // close.
m_sError.Format("failed reuse socket : %d ", WSAGetLastError());
return;
}
// bind : mengikat antara aplikasi dengan port yang dibuat
if(bind(sServer, (struct sockaddr *)&sadd_Server, iSize) == SOCKET_ERROR)
{
m_sError.Format("bind() failed : %d " , WSAGetLastError());
AfxMessageBox(m_sError);
return;
}
nClients=0;
//listen port dengan backlog maksimum
listen(sServer,SOMAXCONN);
CComputer *dlg=reinterpret_cast<CComputer*>(p);
msgcount=dlg->nClients;
iSize=sizeof(dlg->sadd_Client);
dlg->sClient[msgcount]=accept(dlg->sServer,(struct sockaddr *)&(dlg->sadd_Client),&iSize);
if (dlg->sClient[msgcount]==INVALID_SOCKET)
{
AfxMessageBox("Error : invalid socket");
dlg->m_cStartBtn.EnableWindow(TRUE);
return 0;
}else
{
AfxMessageBox(" socket is ready");
dlg->m_cStartBtn.EnableWindow(TRUE);
}
return 0;
}
This might not compile at once, but you should get an idea of how it works.
You should also get into the habit to declare variables not on the top of the function but at the moment you need it. And don't forget to initialize the variables. In your call to setsockopt "opt" is not initialized and the result of the function call is unpredictable.
The declaration of int iSize could be moved to
Code:
int iSize = sizeof(sadd_Server);
I'm off for Christmas now, I wish you a good time playing around with this code. Make sure the CComputer dialog exists until the thread ends.
it work correctly yesterday, but now when i run my aplication again i got this message "debug assert failed wincore.cpp line:980" and my aplication can not run now. why is it happened? what must i do now?
i have learned about this, it because my aplcation have live time. but i don't know to correct it.
Please show the code where you declare and define sClient.
Perhaps your overwriting your sockets with this line, that may be
overrunning your buffer and overwriting part of your socket variable
memory.
Note:
If you declare your memory such as this:
Code:
unsigned char sClient[32];
short Port;
int socket;
and then later use the previous loop, you will overrun the buffer and screw up the socket variable.
Have a look at the socket value in the debugger before and after this loop runs. This is
just an example, and may not be exactly what is going on with your code. In debug mode,
the compiler will allow overruns, and in release mode it will most likely have memory exceptions.
This may explain the changes in the code's behavior over time.
We can't really help without a complete source listing.
Last edited by ahoodin; December 24th, 2009 at 11:41 PM.
I can't get the program to run correctly (most likely due to the language settings of the dialog), but if I ignore some of the errors in the debugger I can run up to the call to accept().
What error do you get and where (use the debugger to run the program and look at the call stack). I think the thread runs ok and the CComputer dialog is valid since it stays on the screen. There must be something else ...
BTW, I have used VC10 to run the prog, but that should not make a big difference, I'd assume.
* The Best Reasons to Target Windows 8
Learn some of the best reasons why you should seriously consider bringing your Android mobile development expertise to bear on the Windows 8 platform.