|
I highly recommend Modern C++ Design: Generic Programming and Design Patterns Applied by Andrei Alexandrescu.
Kuphryn
|
|
|
|
|
Hello
I got problems with serial communications, I use workerthread and overlapped io.
Everything works really nice on one computer, but on another one it dont.
ReadFiles overlapped read event doesnt get triggered, Writefile works as it should.
What can be wrong?
|
|
|
|
|
This code is run on both computer. The only diffrent setting is the comport.
If I connect to the port with hyperterminal I get OK.
DWORD Datatal::CSerialSocket::Connect()
{
//Disconnect if we are connected.
if (m_hComm)
{
CloseHandle(m_hComm);
}
//Lets connect to the port
char szPortName[10];
sprintf(szPortName, "\\\\.\\COM%d", m_dwComPort);
m_hComm = CreateFile(
szPortName, // Name
of port
GENERIC_READ|GENERIC_WRITE, // access ( read and write)
0, // (share) 0: cannot share
the COM port
0, // security (None)
OPEN_EXISTING, // creation : open_existing
FILE_FLAG_OVERLAPPED, // we want overlapped
operation FILE_FLAG_OVERLAPPED
0 // no templates file for
COM port...
);
// Check if we could open the port
if (m_hComm == INVALID_HANDLE_VALUE)
{
DWORD dwRes = GetLastError();
if (ERROR_ACCESS_DENIED == dwRes) WriteLog(1, "Connect
failed, Port is already open");
if (ERROR_FILE_NOT_FOUND == dwRes) WriteLog(1, "Connect
failed, The specified port do not exist");
WriteLog(1, "Connect failed, CreateFile, unspecified
error: %d", dwRes);
return dwRes;
}
//Com settings structure
DCB dcb = {0};
dcb.DCBlength = sizeof(DCB);
if (!GetCommState (m_hComm, &dcb))
{
CloseHandle(m_hComm);
DWORD dwRes = GetLastError();
WriteLog(1, "Connect failed, GetCommState, unspecified
error: %d", dwRes);
return dwRes;
}
dcb.fBinary=TRUE;
dcb.fDsrSensitivity=false;
dcb.fOutX=false;
dcb.fInX=false;
dcb.fNull=false;
dcb.fAbortOnError=TRUE;
dcb.fOutxCtsFlow=FALSE;
dcb.fOutxDsrFlow=false;
dcb.fDtrControl=DTR_CONTROL_DISABLE;
dcb.fDsrSensitivity=false;
dcb.fRtsControl=RTS_CONTROL_DISABLE;
dcb.fOutxCtsFlow=false;
dcb.fOutxCtsFlow=false;
// custom
dcb.BaudRate = m_dwBaudRate;
dcb.ByteSize = m_bByteSize;
dcb.Parity = m_bParity;
if ( m_dwStopBits == 1 )
dcb.StopBits = ONESTOPBIT;
else if (m_dwStopBits == 2 )
dcb.StopBits = TWOSTOPBITS;
else
dcb.StopBits = ONE5STOPBITS;
//Tell the comport how it should work.
if (!SetCommState (m_hComm,&dcb))
{
CloseHandle(m_hComm);
DWORD dwRes = GetLastError();
WriteLog(1, "Connect failed, SetCommState, unspecified
error: %d", dwRes);
return dwRes;
}
// We want to Receive events.
//SetCommMask( m_hComm, EV_RXCHAR|EV_TXEMPTY);
// Set some timeouts.
COMMTIMEOUTS timeouts;
if(!GetCommTimeouts (m_hComm, &timeouts))
{
CloseHandle(m_hComm);
DWORD dwRes = GetLastError();
WriteLog(1, "Connect failed, GetCommTimeouts,
unspecified error: %d", dwRes);
return dwRes;
}
WriteLog(2, "timeouts: ReadInterval: %d, ReadTotalConstant: %d,
ReadTotalMultiplier: %d, WriteTotalConstant: %d, WriteTotalMultiplier:
%d",
timeouts.ReadIntervalTimeout,
timeouts.ReadTotalTimeoutConstant,
timeouts.ReadTotalTimeoutMultiplier,
timeouts.WriteTotalTimeoutConstant,
timeouts.WriteTotalTimeoutMultiplier
);
//defaults, I think...
//ReadInterval: 10, ReadTotalConstant: 0, ReadTotalMultiplier:
0, WriteTotalConstant: 5000, WriteTotalMultiplier: 0
timeouts.ReadIntervalTimeout = 10; // time
between chars
timeouts.ReadTotalTimeoutConstant = 0; //
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 5000;
timeouts.WriteTotalTimeoutMultiplier = 0;
if(!SetCommTimeouts (m_hComm, &timeouts))
{
CloseHandle(m_hComm);
DWORD dwRes = GetLastError();
WriteLog(1, "Connect failed, SetCommTimeouts,
unspecified error: %d", dwRes);
return dwRes;
}
//Flush the port.
//PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR |
PURGE_RXABORT | PURGE_TXABORT);
// Done with connecting, launch the thread
ResetEvent(m_hStopEvent);
ResetEvent(m_hNewDataEvent);
// start the thread
if (!m_bThreadRunning)
{
WriteLog(1, "Connect OK, Trying to start the thread");
Start();
}
else
WriteLog(1, "Connect OK, Thread is already running");
//connect
HandleConnect();
return 0;
}
unsigned __stdcall Datatal::CSerialSocket::ThreadFunc(void* pClient)
{
OVERLAPPED ovRead, ovWrite,
ovEvents;
HANDLE hEvents[5];
DWORD dwWait;
bool bCanRun = true;
DWORD dwEventMask;
bool bSending = false;
bool bReading = false;
bool bNewData = false;
bool bReadComplete = false;
char
szInBuffer[_COMLIB_WORK_SIZE_]; //Out workbuffer,
char
szOutBuffer[_COMLIB_WORK_SIZE_]; //Out workbuffer,
DWORD dwBytesRead = 0;
DWORD dwFlags = 0;
//fetch the parameters
CSerialSocket& client =
*(CSerialSocket*)pClient;
client.WriteLog(2, "ThreadFunc, Thread is running...");
// Overlapped structures.
memset(&ovRead, 0, sizeof(ovRead));
memset(&ovWrite, 0, sizeof(ovWrite));
memset(&ovEvents, 0, sizeof(ovEvents));
//Create events
ovRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!ovRead.hEvent)
{
client.m_bThreadRunning = false;
client.WriteLog(1, "Failed to create ovRead event: %d",
GetLastError());
return 0;
}
ovWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!ovWrite.hEvent)
{
client.m_bThreadRunning = false;
client.WriteLog(1, "Failed to create ovWrite event: %d",
GetLastError());
return 0;
}
ovEvents.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!ovEvents.hEvent)
{
client.m_bThreadRunning = false;
client.WriteLog(1, "Failed to create ovEvents event:
%d", GetLastError());
return 0;
}
//Event array
hEvents[0] = client.m_hStopEvent;
hEvents[1] = ovRead.hEvent;
hEvents[2] = ovWrite.hEvent;
hEvents[3] = ovEvents.hEvent;
hEvents[4] = client.m_hNewDataEvent;
// Want to know when some new data have arrived.
dwEventMask = EV_RXCHAR;
//Tell the class that we are running know
client.m_bThreadRunning = true;
while ( bCanRun )
{
//If we are not connected, do a sleep and then continue.
Do this until we are signalled to stop.
if (!client.IsConnected() && bCanRun)
{
bSending = false;
bReading = false;
bNewData = false;
bReadComplete = false;
//Check if we should reconnect.
if (client.GetReconnect())
{
client.WriteLog(3, "Threadfunc,
Reconnect!");
client.Connect();
}
if (!client.IsConnected())
{
client.WriteLog(2, "ThreadFunc, Waiting
15 seconds or on die event..");
DWORD dwRes =
WaitForSingleObject(client.m_hStopEvent, 15000);
if (dwRes == WAIT_OBJECT_0) bCanRun
= false;
continue;
} // if (!client.IsConnected())
else
Sleep(1000);
}
// Tell us that we want to Receive data
if (bReading)
dwWait = WaitForMultipleObjects (5, hEvents,
FALSE, INFINITE);
else
dwWait = 1000; //will not be found in the
switch.
switch ( dwWait )
{
// Stop event
case WAIT_OBJECT_0:
bCanRun = false;
client.WriteLog(1, "DIE EVENT triggered.");
continue;
break;
// Overlapped Read is completed.
case WAIT_OBJECT_0 + 1:
client.WriteLog(2, "Read -> completed");
ResetEvent(ovRead.hEvent);
bReadComplete = true;
break;
// Overlapped write is completed.
case WAIT_OBJECT_0 + 2:
client.HandleSendComplete();
ResetEvent(ovWrite.hEvent);
bSending = false;
if (client.m_nOutBufSize)
bNewData = true;
else
bNewData = false;
client.WriteLog(2, "Write -> completed");
break;
// A Send() have been done.
case WAIT_OBJECT_0 + 4:
client.WriteLog(1, "send -> triggered");
ResetEvent(client.m_hNewDataEvent);
bNewData = true;
break;
// Received new data
case WAIT_OBJECT_0 + 3:
client.WriteLog(1, "read -> event");
ResetEvent(ovEvents.hEvent); //reset it before.
break;
case 1000:
break;
default:
client.WriteLog(1, "ThreadFunc, Incorrect dwRes:
%d, error: %d\n", dwWait, GetLastError());
break;
} //switch
//dwBytesRead = 0;
if (!bReading)
{
bReading = true;
bReadComplete = false;
memset(szInBuffer, 0, _COMLIB_WORK_SIZE_);
//_COMLIB_WORK_SIZE_
client.WriteLog(3, "read -> ReadFile, event:
%d", ovRead.hEvent);
if (!ReadFile(client.m_hComm, szInBuffer, 1,
&dwBytesRead, &ovRead))
{
int nErr = GetLastError();
if (nErr != ERROR_IO_PENDING)
{
client.WriteLog(1, "ReadFile
failed! Error %d.\n", GetLastError());
client.Disconnect();
client.HandleDisconnect();
continue;
}
client.WriteLog(3, "Read -> Pending read
inited", dwBytesRead);
}
else
{
client.WriteLog(3, "Read -> completed
directly, %d bytes", dwBytesRead);
if (dwBytesRead == 0)
{
bReadComplete = false;
bReading = false;
client.WriteLog(3, "Read ->
Nothing read, hotfix, do a read again.");
}
else
{
bReadComplete = true;
bReading = false;
}
}
}
if (bReadComplete)
{
//If a read was not completed directly,
dwReadBytes = 0, fetch overlapped result.
if (dwBytesRead == 0)
{
dwFlags = 0;
if(!GetOverlappedResult(client.m_hComm,
&ovRead, &dwBytesRead, false))
{
client.WriteLog(1,
"GetOverlappedResult() failed on Read! Bytes read is %d. Error %d.\n",
dwBytesRead, GetLastError());
client.Disconnect();
client.HandleDisconnect();
continue;
}
}
//Closed?
if ( dwBytesRead == 0)
{
client.WriteLog(1, "Socket closed by
Host when waiting for Read..\n");
client.Disconnect();
client.HandleDisconnect();
continue;
}
client.m_critRead.Lock();
if (client.m_nInBufSize + dwBytesRead >
_COMLIB_IN_SIZE_)
{
client.m_critRead.Unlock();
client.WriteLog(1, "Read -> BUFFER
OVERFLOW, disconnecting");
client.Disconnect();
continue;
}
//Copy Received data to our inbuffer
memcpy(client.m_pInBuf + client.m_nInBufSize,
szInBuffer, dwBytesRead);
client.m_nInBufSize += dwBytesRead;
client.WriteLog(3, "Read -> Data: %s, bytes:
%d", szInBuffer, dwBytesRead);
//Tell derived class that new data is in the
buffer
//More than one packet can be in the same
buffer, so handle it.
int nBytesOk;
nBytesOk = client.HandleReceive(client.m_pInBuf,
client.m_nInBufSize);
client.WriteLog(3, "Read -> Bytes handled: %d",
nBytesOk);
//Check if there are more data to trigger on.
int nByteCount = nBytesOk;
while (nBytesOk && (nByteCount <
client.m_nInBufSize))
{
nBytesOk =
client.HandleReceive(client.m_pInBuf + nByteCount, client.m_nInBufSize -
nByteCount);
client.WriteLog(3, "Read -> Bytes
handled2: %d", nBytesOk);
nByteCount += nBytesOk;
}
//derived class should return the number of
bytes that were accepted
//remove those bytes from the buffer
if (nByteCount > 0)
{
//WHole buffer?
if (nByteCount == client.m_nInBufSize)
{
client.WriteLog(3, "Read ->
Cleahing whole buffer");
memset(client.m_pInBuf, 0,
_COMLIB_IN_SIZE_);
client.m_nInBufSize = 0;
}
else
{
client.WriteLog(3, "Read ->
Cleaing partial buffer");
memmove(client.m_pInBuf,
client.m_pInBuf + nByteCount, client.m_nInBufSize - nByteCount);
client.m_nInBufSize -=
nByteCount;
} //if (nBytesOk == *pTP->pnInBufSize)
} //if (nBytesOk > 0)
memset(szInBuffer, 0, _COMLIB_WORK_SIZE_);
bReadComplete = false;
bReading = false;
client.m_critRead.Unlock();
}
//We gotto write some stuff, and we only do it if no
operations are ongoing
if (bNewData && !bSending)
{
//Lock buffer and fetch data
client.m_critWrite.Lock();
ResetEvent(client.m_hNewDataEvent);
bSending = true;
int nBufferLen = 0;
//TODO: large for our workbuffer?
if (client.m_nOutBufSize > _COMLIB_WORK_SIZE_)
{
memcpy(szOutBuffer, client.m_pOutBuf,
_COMLIB_WORK_SIZE_); // fill the buffer
memmove(client.m_pOutBuf,
client.m_pOutBuf + _COMLIB_WORK_SIZE_, client.m_nOutBufSize -
_COMLIB_WORK_SIZE_);
memset(client.m_pOutBuf +
_COMLIB_OUT_SIZE_ - _COMLIB_WORK_SIZE_, 0, _COMLIB_OUT_SIZE_ -
_COMLIB_WORK_SIZE_);
nBufferLen = _COMLIB_WORK_SIZE_;
client.m_nOutBufSize -=
_COMLIB_WORK_SIZE_;
}
else
{
memcpy(szOutBuffer, client.m_pOutBuf,
client.m_nOutBufSize);
memset(client.m_pOutBuf, 0,
_COMLIB_OUT_SIZE_);
nBufferLen = client.m_nOutBufSize;
client.m_nOutBufSize = 0;
}
DWORD dwBytesWritten;
if (!WriteFile(client.m_hComm, szOutBuffer,
nBufferLen, &dwBytesWritten, &ovWrite))
{
//Overlapped?
if (GetLastError() != ERROR_IO_PENDING)
{
client.m_critWrite.Unlock();
client.WriteLog(3, "WriteFile()
failed! Error %d", GetLastError());
client.Disconnect();
client.HandleDisconnect();
break;
}
bSending = true; //only set pending
write if we do not complete directly.
}
else
bSending = false;
client.m_critWrite.Unlock();
} //if (!bSending && !bReading)
} //while
client.m_bThreadRunning = false;
return 0;
}
|
|
|
|
|
WiB wrote:
You didn't answer my questions:
1. Do you connect 2 PC via COM?
2. Did you check settings of both COM?
1. On one server i communicate with the same PC (both ports are on a digibort)
On the other (nonworking) server i communicate with a PABX.
2. Yes. The only diffrence is the type of comports. On the nonworking server it's USB serial port, and on the working server it's DigiBord comports.
Well.. Can you please check the connect function, Im not sure if the DCB and Timeoutsettings are correct.
|
|
|
|
|
can you check my Connect function anyway?
Since hyperterminal can recieve data from the port, it must be something with my program. And Im really desperate to find out what.
|
|
|
|
|
hii,
for any call of this function EnumDisplayDevices(..) , It generate error when compilation , "undeclared identifier" without any acceptable reason !!
any one can help of that ,
- I made all needed includes ! ,
hatem
|
|
|
|
|
thank u ,
but I do so , but nothing changed !! , still "undeclared identifier" !!!
I really don't know why !!!
hatem
|
|
|
|
|
there is ,
in customize ..
user32.lib /nologo /subsystem:windows /incremental:yes /pdb:"Debug/test005.pdb" /debug /machine:I386 /out:"Debug/test005.exe" /pdbtype:sept
|
|
|
|
|
#include <multimon.h>
In one (and only one) file that includes this file, include this line before the #include line:
#define COMPILE_MULTIMON_STUBS
This will enable the use of the multi-monitor functions on any platform (even though Win95 does not support multiple monitors) and degrade gracefully if they are not supported.
Ryan
Being little and getting pushed around by big guys all my life I guess I compensate by pushing electrons and holes around. What a bully I am, but I do enjoy making subatomic particles hop at my bidding - Roger Wright (2nd April 2003, The Lounge)
Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late - John Nichol "Point Of Impact"
|
|
|
|
|
thank you.. .. but
nothing changed ! , still "undeclared indentifier"
with ..
#include <windows.h>
#include <multimon.h>
#define COMPILE_MULTIMON_STUBS
void main()
{
DISPLAY_DEVICE dd;
EnumDisplayDevices(0, 0, &dd, 0);
}
and , "unresolved external symbol __imp__EnumDisplayDevicesA@16"
with ..
#define WINVER 0x0500
#include <windows.h>
#include <multimon.h>
#define COMPILE_MULTIMON_STUBS
void main()
{
DISPLAY_DEVICE dd;
EnumDisplayDevices(0, 0, &dd, 0);
}
and if I repaced the windows.h & multimon.h it make 29 error !!!
I eally disappointed !!
|
|
|
|
|
I said to place the #define COMPILE_MULTIMON_STUBS line BEFORE the #include <multimon.h> line, not after.
Ryan
Being little and getting pushed around by big guys all my life I guess I compensate by pushing electrons and holes around. What a bully I am, but I do enjoy making subatomic particles hop at my bidding - Roger Wright (2nd April 2003, The Lounge)
Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late - John Nichol "Point Of Impact"
|
|
|
|
|
I did , nothing happened !!
the same error ,
I want to tell u that I seached in User32.lib , I find all enum function , but EnumDisplayDevices does not exit at all !!! ,
I MSDN they say that this function exists in User32.LIB !! ,
I wonder if there is another function , instead of this unexist one !!
hatem
|
|
|
|
|
The code that you posted has the #define line after the #include line, so I assumed that this was the code you were testing.
The function works perfectly. I have used it plenty of times before. Try this:
#include <windows.h>
#define COMPILE_MULTIMON_STUBS
#include <multimon.h>
int WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
{
DISPLAY_DEVICE dd;
dd.cb = sizeof(DISPLAY_DEVICE);
for(int i=0; EnumDisplayDevices(NULL, i, &dd, 0); i++)
{
}
return 0;
}
Ryan
Being little and getting pushed around by big guys all my life I guess I compensate by pushing electrons and holes around. What a bully I am, but I do enjoy making subatomic particles hop at my bidding - Roger Wright (2nd April 2003, The Lounge)
Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late - John Nichol "Point Of Impact"
|
|
|
|
|
sorry ,
but I tryed your code , and the same problem occures , !! , I think it may be the problem of Windows2000 , or some thing wrong with my VC++ !! ,
hatem
|
|
|
|
|
please could u send me a sample application , that this function is work in it ,
my mail is , hatem_poet@menanet.net
|
|
|
|
|
There's something wrong with what you're doing. I compiled exactly the code that I posted before, and it compiled with only one warning, which could be safely ignored.
Sorry, I can't help any more than this. I don't know what you're doing wrong. You'll have to sort it out there.
Ryan
Being little and getting pushed around by big guys all my life I guess I compensate by pushing electrons and holes around. What a bully I am, but I do enjoy making subatomic particles hop at my bidding - Roger Wright (2nd April 2003, The Lounge)
Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late - John Nichol "Point Of Impact"
|
|
|
|
|
i want to show a CFrameWnd window responding to a buttonclicked event in a dialog based application .the application has no doc template. and i have some problem to realize that.
the following are my codes:
CMainFrame myframe;
myframe.LoadFrame(.....);
myframe.CreateView(....);
myFrame.ShowWindow(...);
if you have any experience on that,pls tell whether i can do like that.
perhaps i have made some ridiculous mistake...
gucy
|
|
|
|
|
Hi,
Can I use LogonUser w/o knowing a particular users' password?
Regards
Srinivas
|
|
|
|
|
no and yes.
For 'normal' programming it is quite impossible.
Only way that is possible is to provide a subauthentication dll to the LSA, that will take any or none password as valid.
But you must install such a dll to the system locally under administration rights and it should also work only for local accounts.
|
|
|
|
|
No, unless you can hack it.
|
|
|
|
|
Hi,EveryOne
I want one formview(MDI) of data can transfer to other formview(which also A MDI). One formview I am using listbox and othe formview i am using editbox.
Thanxs
|
|
|
|
|
I have few edit boxes (for double prec. numbers)in a dialog (in a dialog based MFC program).
I want to go to the next edit box when I press ENTER. Normally the control goes to OnOk and the program exits.
Similarly I want to reset (to blank) all the data in the edit boxes when I press ESCAPE. But the program closes when I do so.
Will someone help?
|
|
|
|
|
override OnCancel() and OnOk() functions in your dialog message map
so you can write your own code for these keys
|
|
|
|
|
This question was asked a few days ago... Override PreTranslateMessage() like this:
BOOL CMyDialog::PreTranslateMessage(MSG *pMsg)
{
if((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_RETURN))
pMsg->wParam = VK_TAB;
return CDialog::PreTranslateMessage(pMsg);
} This should work as required.
Ryan
Being little and getting pushed around by big guys all my life I guess I compensate by pushing electrons and holes around. What a bully I am, but I do enjoy making subatomic particles hop at my bidding - Roger Wright (2nd April 2003, The Lounge)
Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late - John Nichol "Point Of Impact"
|
|
|
|
|
as title
|
|
|
|
|