|
Can you please show some examples ?
Thanks,
Nice things do nice works
|
|
|
|
|
So which part do you need help with: creating an exported function in C, or using said function in VB?
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles
|
|
|
|
|
both parts (full sample program)
Thanks,
|
|
|
|
|
Read point #2 here.
As to how to export a function from a DLL, see here.
For declaring a reference to an external function in a DLL, see here.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles
|
|
|
|
|
Hi,
There is a really old article from 2005[^] that demonstrates how to do this. If you scroll to the bottom of the forum you might find a younger Randor lurking there. His username wasn't even red like a rooster yet.
Best Wishes,
-David Delaune
|
|
|
|
|
«_Superman_»
I love work. It gives me something to do between weekends.
Microsoft MVP (Visual C++) (October 2009 - September 2013) Polymorphism in C
|
|
|
|
|
Hi I have Dialog based mfc applciation using visual studio 2013.
Dialog contains multiple controls. It has two threads - main ui thread and worker thread
In a particular control (some static test) i have to show some counts (like number of Cars produced
and Number of Bikes prodcued, and total ). Actually these counts are given by worker thread.
Worker thread continuously gives the counts (that is live data)
I have to update UI from main thread based on these data lively.
Please help me to design this use case. My ui contains multiple controls. I don't want to block the UI
How to pass the data(counts) from worker thread to main thread? how to avoid block in main thread?
Is there any need for queue or another thread?
That is UI will be some thing like
number of Cars produced:10
number of Bikes produced: 20
Total: 30
|
|
|
|
|
Member 11426624 wrote: Is there any need for queue or another thread?
No, you could just use the PostMessage function[^] from the worker thread to pass a custom window message[^] to the UI thread to update the counts and that would be non-blocking.
Best Wishes,
-David Delaune
|
|
|
|
|
|
I'm using Visual C++ Professional Version 2015 update 3. I have a program that automates Excel and works fine in our Windows 7 computers. However, on Windows 10, Excel doesn't even launch (CreateDispatch() returns 0).
There is a problem with a Windows Function, CLSIDFromProgID(L"Excel.Application", &clsid), which returns error 0x800401fe, which has the explanation: “Application was launched but it didn't register a class factory”. This is a curious explanation because all the function does is pick up the CLSID from the registry (it doesn’t launch Excel). And “Excel.Application” is in the registry for the Windows 10 computer just like for our Windows 7 computers. I was thinking that maybe Windows 10 doesn’t allow automation to work from clients that are from an “unknown publisher”, but then it should work with UAC off. (And when I ran it with UAC set to "never notify", the warning message did not appear when starting PI_Dats. Maybe it’s not really disabled, it just doesn’t issue the warning?)
On the Local Disk Properties Security tab, Administrators have full control and I set Users also to full control. Any ideas on how to automate Excel from Windows 10 would be greatly appreciated.
Thanks,
Gary
|
|
|
|
|
|
|
Appcues — Increase Product Adoption. Code-Free.
create overlay guided user experiences
Like add tootips/message to show workflow in applications ? for example to highlight new features ? or to guide new users around the software ?
Do you know if such things exists for Win32/MFC ?
Thanks.
I'd rather be phishing!
|
|
|
|
|
We have a MFC based Server and a Client application that communicates using TCP/IP Sockets. The Server application is a dynamic Calculation engine for Chemical Process plant and does calculations continuously and responds to dynamic inputs from the client. The plant values (structure) are sent every second using a thread with a frequency of 1 second and the values are received in the client using a thread with the same frequency of 1 second. The total size of the data sent through the sockets is around 2500bytes/second. We use socket serialization through a Class derived from CObject for sending and receiving data through sockets. This application runs fine in the LAN and initially the applications were developed to run in LAN Environment.
When I try to run the applications in internet by using a static IP address for the server, the communication is established and the values are send and received successfully. However, when the applications are run for a period of more than 2 hours one of the following result is observed repeatedly.
1. The client application hangs up and shows no response.
2. Both the server and client gets disconnected but runs independently without any data exchange.
3. The client application gets closed which may be after an application crash.
Note: The same applications run for more than 15 hours without any problems in a LAN setup.
Please help me to understand the underlying problem and provide me a solution for this problem.
|
|
|
|
|
This can't be answered or solved without seeing the related code and knowing about the used protocol and data flow.
However, here are some tips:
With WAN communication, packets might get lost and resend. Packets might arrive in a different order. If order matters, the sequence number of the raw packets can be used or the protocol must provide a similar field (which might be an existing time stamp with adequate resolution).
The receiving threads must be event driven (your post might indicate that they are timer driven).
Check all function return codes and check for timeouts (detect dropped connections). Doing so might solve the problem of the hanging client (possible scenario: client waits for an event or state that is never occuring).
When encountering problems by code, provide methods to gracefully drop a connection so that you can restart. This should be done on both sides which requires the client to be able to send to the server (keep alive messages and close requests).
|
|
|
|
|
I have copied the Server code and Client code below. As of now, both the functions send (Server side) and Receive code (client code) are timer driven with frequency of 1 second. Can you please detail me this step which you had mentioned as "Check all function return codes and check for timeouts (detect dropped connections)." as I am unable to understand that clearly.
This function call in the below code in Server "tFrm->UpdateOprs(&tData);" sends the data to all the connected clients (In my case, I have connected only one Client). This function call ("tFrm->UpdateOprs(&tData);") to send data is called 5 times in a Send cycle and correspondingly 5 calls to receive data in the client side is called.
//Server Side Code
void SendActiveData()
{
POSITION pos;
long int Offset;
CString tString;
CTagBase* OTemp;
int i;
CTrans tData;
CTrans cData[50];
CMainFrame* tFrm = (CMainFrame*)AfxGetMainWnd();
tFrm->tId = 0;
if(bBackTrkTime)
{
bBackTrkTime = false;
tData.Init();
for(i=0;i<livedatacount.count;i++)
tdata.m_sdata.insert(i,livearray[i]);
="" tfrm-="">UpdateOprs(&tData);
LiveArray[0] = Esim->HOLD;
return;
}
if(bModelChange)
{
bModelChange = false;
tData.Init();
for(i=0;i<livedatacount.count;i++)
tdata.m_sdata.insert(i,livearray[i]);
="" tfrm-="">UpdateOprs(&tData);
LiveArray[0] = Esim->HOLD;
return;
}
if(!bMesgToOpr)
LiveArray[0]=Esim->HOLD;
else
{
bMesgToOpr = FALSE;
tData.Init();
for(i=0;i<livedatacount.count;i++)
tdata.m_sdata.insert(i,livearray[i]);
="" tfrm-="">UpdateOprs(&tData);
return;
}
Offset = 1;
pos = OLivePointList.GetHeadPosition();
if(OPSTATION == CENTUMXL || OPSTATION == CS3000|| OPSTATION == FOXBORO || OPSTATION == CENTUMVP || OPSTATION == EXPERION || OPSTATION == ABB || OPSTATION == DELTAV
|| OPSTATION == SIEMENS || OPSTATION == TDC3000)
{
for(i=0;i<controllercount;i++)
{
="" otemp="(CTagBase*" )="" olivepointlist.getat(pos);
="" cstring="" str="OTemp-">GetTagName();
unsigned char* Temp = OTemp->SendLivePoints();
long lTemp = Offset+(i*LIVECONSIZE);
for(int j = 0; j < LIVECONSIZE; j++)
{
LiveArray[lTemp] = Temp[j];
lTemp++;
}
OLivePointList.GetNext(pos);
}
Offset += (ControllerCount*LIVECONSIZE);
for(i=0;i<indicatorcount;i++)
{
="" otemp="(CTagBase*" )="" olivepointlist.getat(pos);
="" unsigned="" char*="" temp="OTemp-">SendLivePoints();
long lTemp = Offset + (i * LIVEINDSIZE);
for(int j = 0; j < LIVEINDSIZE; j++)
{
LiveArray[lTemp] = Temp[j];
lTemp++;
}
OLivePointList.GetNext(pos);
}
Offset += IndicatorCount*LIVEINDSIZE;
for(i=0;i<switchcount;i++)
{
=""
="" otemp="(CTagBase*" )="" olivepointlist.getat(pos);
="" unsigned="" char*="" tem="OTemp-">SendLivePoints();
long lTemp = Offset + (i * LIVESWTSIZE);
for(int j = 0; j < LIVESWTSIZE; j++)
{
LiveArray[lTemp] = Tem[j];
lTemp++;
}
OLivePointList.GetNext(pos);
}
Offset += SwitchCount*LIVESWTSIZE;
for(i=0;i<eswitchcount;i++)
{
="" unsigned="" char="" tswitch[2]="{0};
" otemp="(CTagBase*" )="" olivepointlist.getat(pos);
="" tswitch[0]="*(OTemp-">SendLivePoints());
long TmpOffset = Offset + (i * LIVESWTSIZE);
Tswitch[0] = *(OTemp->SendLivePoints());
(LiveArray[TmpOffset]) = Tswitch[0];
OLivePointList.GetNext(pos);
}
Offset += ESwitchCount*LIVESWTSIZE;
for(i=0;i<globecount;i++)
{
="" otemp="(CTagBase*" )="" olivepointlist.getat(pos);
="" unsigned="" char="" *ggg,="" gg[4];
="" ggg="(unsigned" char*="" )otemp-="">SendLivePoints();
GG[0]=GGG[0];
GG[1]=GGG[1];
GG[2]=GGG[2];
GG[3]=GGG[3];
memmove((void* )((LiveArray+Offset)+(i*LIVEGLBSIZE)),GG,4);
OLivePointList.GetNext(pos);
}
Offset += GlobeCount*LIVEGLBSIZE;
long TmpOffset;
for(i=0;i<alarmcount;i++)
{
="" otemp="(CTagBase*" )="" olivepointlist.getat(pos);
="" tmpoffset="Offset+(i*LIVEALMLITSIZE);
" unsigned="" char="" *palarm="OTemp-">SendLivePoints();
LiveArray[TmpOffset] = pAlarm[0];
OLivePointList.GetNext(pos);
}
Offset += AlarmCount*LIVEALMLITSIZE;
for(i=0;i<lightcount;i++)
{
="" otemp="(CTagBase*" )="" olivepointlist.getat(pos);
="" long="" tmpoffset="Offset+(i*LIVEALMLITSIZE);
" unsigned="" char="" *plight="OTemp-">SendLivePoints();
LiveArray[TmpOffset] = pLight[0];
OLivePointList.GetNext(pos);
}
Offset += LightCount*LIVEALMLITSIZE;
for(i=0;i<amscount;i++)
{
="" otemp="(CTagBase*" )="" olivepointlist.getat(pos);
="" long="" tmpoffset="Offset+(i*LIVEAMSSIZE);
" unsigned="" char="" *pams="OTemp-">SendLivePoints();
for(int j = 0; j < LIVEAMSSIZE; j++)
{
LiveArray[TmpOffset] = pAms[j];
TmpOffset++;
}
OLivePointList.GetNext(pos);
}
Offset += AmsCount*LIVEAMSSIZE;
}
if(OPSTATION == HONEYWELL)
{
for(i=0;i<controllercount;i++)
{
="" otemp="(CTagBase*" )="" olivepointlist.getat(pos);
="" unsigned="" char*="" temp="OTemp-">SendLivePoints();
long lTemp = Offset+(i*LIVECONSIZE);
for(int j = 0; j < LIVECONSIZE; j++)
{
LiveArray[lTemp] = Temp[j];
lTemp++;
}
OLivePointList.GetNext(pos);
}
Offset += (ControllerCount*LIVECONSIZE);
for(i=0;i<indicatorcount;i++)
{
="" otemp="(CTagBase*" )="" olivepointlist.getat(pos);
="" unsigned="" char*="" temp="OTemp-">SendLivePoints();
long lTemp = Offset + (i * LIVEINDSIZE);
for(int j = 0; j < LIVEINDSIZE; j++)
{
LiveArray[lTemp] = Temp[j];
lTemp++;
}
OLivePointList.GetNext(pos);
}
Offset += IndicatorCount*LIVEINDSIZE;
for(i=0;i<switchcount;i++)
{
="" otemp="(CTagBase*" )="" olivepointlist.getat(pos);
="" unsigned="" char*="" tem="OTemp-">SendLivePoints();
long lTemp = Offset + (i * LIVESWTSIZE);
for(int j = 0; j < LIVESWTSIZE; j++)
{
LiveArray[lTemp] = Tem[j];
lTemp++;
}
OLivePointList.GetNext(pos);
}
Offset += SwitchCount*LIVESWTSIZE;
for(i=0;i<eswitchcount;i++)
{
="" unsigned="" char="" tswitch[2]="{0};
" otemp="(CTagBase*" )="" olivepointlist.getat(pos);
="" tswitch[0]="*(OTemp-">SendLivePoints());
long TmpOffset = Offset + (i * LIVESWTSIZE);
Tswitch[0] = *(OTemp->SendLivePoints());
(LiveArray[TmpOffset]) = Tswitch[0];
OLivePointList.GetNext(pos);
}
Offset += ESwitchCount*LIVESWTSIZE;
for(i=0;i<globecount;i++)
{
="" otemp="(CTagBase*" )="" olivepointlist.getat(pos);
="" unsigned="" char*="" temp="OTemp-">SendLivePoints();
long lTemp = Offset + (i * LIVEGLBSIZE);
for(int j = 0; j < LIVEGLBSIZE; j++)
{
LiveArray[lTemp] = Temp[j];
lTemp++;
}
OLivePointList.GetNext(pos);
}
Offset += GlobeCount*LIVEGLBSIZE;
long TmpOffset;
for(i=0;i<alarmcount;i++)
{
="" otemp="(CTagBase*" )="" olivepointlist.getat(pos);
="" tmpoffset="Offset+(i*LIVEALMLITSIZE);
" unsigned="" char="" *palarm="OTemp-">SendLivePoints();
LiveArray[TmpOffset] = pAlarm[0];
OLivePointList.GetNext(pos);
}
Offset += AlarmCount*LIVEALMLITSIZE;
for(i=0;i<lightcount;i++)
{
="" otemp="(CTagBase*" )="" olivepointlist.getat(pos);
="" tmpoffset="Offset+(i*LIVEALMLITSIZE);
" unsigned="" char="" *plight="OTemp-">SendLivePoints();
LiveArray[TmpOffset] = pLight[0];
OLivePointList.GetNext(pos);
}
Offset += LightCount*LIVEALMLITSIZE;
}
tData.Init();
for(i=0;i<livedatacount.count;i++)
="" tdata.m_sdata.insert(i,livearray[i]);
="" int="" ilen="tData.m_sData.GetLength();
" tfrm-="">UpdateOprs(&tData);
Sleep(5);
char gAcknowledge[50];
memset(gAcknowledge,0,50);
int clntCount = tFrm->m_connectionList.GetCount();
cData[0].Init();
for(i = 0;i < clntCount;i++)
cData[i].Init();
tFrm->UpdateRequests(cData);
Acknowledge = FALSE;
for(i = 0;i < clntCount;i++)
{
if(cData[i].m_sData.GetLength())
{
gAcknowledge[i] = cData[i].m_sData.GetAt(0);
if(gAcknowledge[i] == TRUE)
{
Acknowledge = gAcknowledge[i];
}
}
}
char cFlag = Acknowledge;
if(InstClosedFlag==TRUE)
Acknowledge = __CLOSED;
tData.Init();
tData.m_sData.Insert(0,Acknowledge);
tFrm->UpdateOprs(&tData);
Sleep(5);
if(cFlag == TRUE)
{
cData[0].Init();
for(i = 0;i < clntCount;i++)
cData[i].Init();
tFrm->UpdateRequests(cData);
Sleep(5);
for(i = 0; i < clntCount;i++)
{
if(gAcknowledge[i] == TRUE)
{
int temp = cData[i].m_sData.GetLength();
for(int j = 0; j < temp; j++)
InstChangeString[j] = cData[i].m_sData.GetAt(j);
ChangeInstValues(InstChangeString);
}
}
}
tData.Init();
char cTemp[200];
CString strTemp;
strTemp.Insert(0,INS_BACKTRACK_TIME);
strTemp.Insert(1,bBackTrkTime);
strTemp.Insert(2,strBackTrkTime);
strcpy(cTemp,strTemp);
int nLenTemp = strTemp.GetLength();
for(i=0;i<nlentemp;i++)
{
="" tdata.m_sdata.insert(i,ctemp[i]);
="" }
="" tfrm-="">UpdateOprs(&tData);
if(bBackTrkTime)
{
strBackTrkTime = "";
bBackTrkTime = false;
}
CString STime;
CTime TNow;
TNow = CTime::GetCurrentTime();
STime=TNow.Format("%H:%M:%S");
tData.Init();
char cCurTime[10];
CString sCurTime;
strcpy(cCurTime,STime);
nLenTemp = STime.GetLength();
for(i=0;i<nlentemp;i++)
{
="" tdata.m_sdata.insert(i,ccurtime[i]);
="" }
="" tfrm-="">UpdateOprs(&tData);
sGblTime = STime;
}
//Client Side Code
void RecvActiveData_Ins()
{
static POSITION pos;
CString tString = "";
long int Offset = 0;
int i = 0;
static char nType = 0;
char czCount[10] = {0};
int nCount = 0;
if( InstClosedFlag_Client == TRUE || OprClosedFlag_Client == TRUE )
return;
CTagBase* OTemp;
CTrans oData;
CMainFrame* tFrm = (CMainFrame*)AfxGetMainWnd();
char sTime[10]={0};
oData.Init(LiveDataCount.Count);
tFrm->ReceiveData(&oData);
int nLen = oData.m_sData.GetLength();
memcpy((void*)LiveArray_Client,(const char*)oData.m_sData,nLen);
char StatusHold=LiveArray_Client[0];
if(StatusHold != nModelHoldSvr)
{
nModelHoldSvr = StatusHold;
if (nModelHoldSvr == 1)
{
CMainFrame *pFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd;
if(Esim->HOLD != 1)
pFrame->OnModePause();
}
else
{
CMainFrame *pFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd;
if(Esim->HOLD != 0)
pFrame->OnModeRun();
}
}
if(LiveArray_Client[0] == 2)
{
IsMsgRecvFromInst = TRUE;
return;
}
else if((pos = goTagList.GetHeadPosition())!=NULL)
{
Offset = 1;
for(i=0;i<giconcnt;i++)
{
="" otemp="(CTagBase*" )="" gotaglist.getat(pos);
="" cstring="" str="OTemp-">GetTagName();
OTemp->ReceiveLivePoints((LiveArray_Client+Offset)+(i*LIVECONSIZE));
char str2=OTemp->GetCascade();
goTagList.GetNext(pos);
}
Offset += giConCnt*LIVECONSIZE;
for(i=0;i<giindcnt;i++)
{
="" otemp="(CTagBase*" )="" gotaglist.getat(pos);
="" otemp-="">ReceiveLivePoints((LiveArray_Client+Offset)+(i*LIVEINDSIZE));
goTagList.GetNext(pos);
}
Offset += giIndCnt*LIVEINDSIZE;
int nSwtESwt = giSwtCnt + giESwtCnt;
for(i=0;i<nswteswt;i++)
{
="" otemp="(CTagBase*" )="" gotaglist.getat(pos);
="" otemp-="">ReceiveLivePoints((LiveArray_Client+Offset)+(i*LIVESWTSIZE));
goTagList.GetNext(pos);
}
Offset += nSwtESwt*LIVESWTSIZE;
for(i=0;i<giglbcnt;i++)
{
="" otemp="(CTagBase*" )="" gotaglist.getat(pos);
="" otemp-="">ReceiveLivePoints((LiveArray_Client+Offset)+(i*LIVEGLBSIZE));
goTagList.GetNext(pos);
}
Offset += giGlbCnt*LIVEGLBSIZE;
int nAlrmLght = giAlrmCnt + giLitCnt;
for(i=0;i<nalrmlght;i++)
{
="" otemp="(CTagBase*" )="" gotaglist.getat(pos);
="" otemp-="">ReceiveLivePoints((LiveArray_Client+Offset)+(i*LIVEALMLITSIZE));
goTagList.GetNext(pos);
}
Offset += nAlrmLght*LIVEALMLITSIZE;
for(i=0;i<giamscnt;i++)
{
="" otemp="(CTagBase*" )="" gotaglist.getat(pos);
="" otemp-="">ReceiveLivePoints((LiveArray_Client+Offset)+(i*LIVEAMSSIZE));
goTagList.GetNext(pos);
}
Offset += giAmsCnt*LIVEAMSSIZE;
}
if(gbValueChange == TRUE)
{
Acknowledge_Client=TRUE;
}
else if(OprClosedFlag_Client==TRUE)
{
Acknowledge_Client=__CLOSED;
}
else
{
Acknowledge_Client=FALSE;
}
char TempString[10] = {0};
oData.Init(1);
oData.m_sData.Insert(0,Acknowledge_Client);
tFrm->SendData(&oData);
oData.Init(1);
tFrm->ReceiveData(&oData);
strcpy(TempString,oData.m_sData);
if(TempString[0] == TRUE)
{
oData.Init(28);
for(i = 0; i < 28; i++)
oData.m_sData.Insert(i,gszModifiedTagInfo[i]);
tFrm->SendData(&oData);
gbValueChange = FALSE;
memset( gszModifiedTagInfo, 0, 28 );
}
else if(TempString[0]==__CLOSED)
{
InstClosedFlag_Client=TRUE;
OprClosedFlag_Client=TRUE;
}
char TempBackTrk[250] = {0};
oData.Init(1);
tFrm->ReceiveData(&oData);
strcpy(TempBackTrk,oData.m_sData);
if(TempBackTrk[0] == INS_BACKTRACK_TIME)
{
if(TempBackTrk[1] == true)
{
bBackTrkTime = true;
ReadBackTime_Ins(TempBackTrk);
}
else
bBackTrkTime = false;
}
char cRecServTime[10] = {0};
oData.Init(1);
tFrm->ReceiveData(&oData);
strcpy(cRecServTime,oData.m_sData);
sGblTime = cRecServTime;
}
|
|
|
|
|
That is too much (unformatted) code to check.
Sending data timer driven is fine. But for receiving you should use an own thread that handles the receiving and supports timeouts. Using serializing might be not the best choice.
When not detecting timeouts and the connection is dropped, the read function will wait forever. Even after establishing a new connection, the pending wait will never finish because the new connection uses a different socket handle.
The typical flow of receiving in a worker thread (not using serialization):
while (1)
{
if (StopEvent)
break;
if (TimeOut)
{
}
if (ReceiveEvent)
{
}
if (CompletePackageReceived)
{
}
if (CriticalError) {
break;
}
}
|
|
|
|
|
Thanks for your reply.
Just to mention that I am a novice to socket programming.
As per your suggestion, I changed the receive at the client side by removing the thread and added the OnReceive() event function to receive data from the server. Whenever OnReceive() is called, I called the Receive() to receive the data from the server. Also I removed the Serialization from both the server and client and send the data as a normal packet.
However when I run the server and client and logged the data received time to a file by adding the code to log the current time inside the OnReceive() function of the client, it had run successfully for nearly 10 hours. After that there is no logging of time in the file seen, and I assume that the connection is disconnected between the server and the client and hence the OnReceive() event was not triggered. Please guide me how to handle this and establish a continous connection. Also How to detect if the connection is lost?
|
|
|
|
|
That is why all event waiting calls should have a timeout. If that occurs, the server should close the corresponding socket and go into listen state again. Similar for the client: close and try to connect again.
There is no direct and fast method to detect an interrupted connection. Interrupted in the sense off one side closing the connection without announcement or even network disconnect.
|
|
|
|
|
Can you please provide me MFC code to detect the connection time out or disconnect and to re-connect the server from the client
|
|
|
|
|
It depends on the used socket implementation (raw / POSIX sockets, WinSock, CSocket, or CAsyncSocket Class[^]).
With raw sockets, use the select function (Windows)[^] passing the timeout.
With blocking receive calls, you can set the SO_RCVTIMEO socket option (see setsockopt function (Windows)[^]).
When using CAsyncSocket , you have to implement your own timer that is reset when data are received.
With non-blocking calls you usually wait for events with WaitFor(Single|Multiple)Object(s) which have a timeout parameter. I recommend this when using a worker thread for receiving because the call can also catch a terminate event to stop the thread when closing the connection by intention like when terminating the application.
Once a timeout is detected you close the related connections / sockets like when terminating the application. Afterwards enter the listen state again on the server and try to (re-)connect on the client like when starting the applications.
A complete example - even when knowing the used socket type - would be far too much for this forum. But there are a lot of tutorials in the net and here at CP about the topic.
|
|
|
|
|
Thanks a lot for your reply.
I am using CSocket implementation for server and client with Serialization using a class derived from CObject. As already mentioned, I use a thread to send and receive data continuously every second from Server Side. Similarly I use a thread to send and receive data continuously every second from client Side.
Can I implement this timer suggested by you for CAsyncSocket in my code that is using serialization and continuous send/receive operation. Please suggest how to do it especially to handle connection lost issues (to detect connection failure and reconnect properly) and to avoid crash problems.
Please excuse me for asking too much.
|
|
|
|
|
|
See the CSocket Class[^]. The problems with serialization are described there in the Remarks section.
When using OnReceive() , you can use a timer which is reset in that function. When the timer elapsed, close the connection.
|
|
|
|
|
Thanks for your reply.
In the client side:
I used OnReceive() and a timer variable which is reset to zero in that function. In a separate thread of 1 second frequency, I increment the timer variable to one. So every one second the timer variable is incremented but it is reset to zero in the OnReceive since the data is received in OnReceive() which is sent by the server every second. When the timer variable exceeds 30 counts, it is elapsed. When the timer is elapsed, I closed the client socket using shutdown and deleted the socket.
But When I tested the Server and the client, the server hangs after some 2 hours. Previously my client got hanged or lost connection.
Any suggestion, why the server is getting hanged this time?
|
|
|
|