|
| Sockets again... |
 |
Thu, 16 Feb 2006 15:38:21 +010 |
Dear Symbian-Developers,
I've got the following problem: My Symbian-web-server just doesn't work as
it should...
As mentioned in other tutorials, I'm doing the following:
//member-vars:
RSocket iListener;
RSocketServ iServer;
RSocket iblankSocket;
TBuf8<1000> iBuffer;
RFile iFile;
User::LeaveIfError(iServer.Connect(2));
User::LeaveIfError(iFs.Connect());
TInetAddr address(KInetAddrLoop, 80);
User::LeaveIfError(iListener.Open(iServer, KAfInet, KSockStream,
KProtocolInetTcp));
User::LeaveIfError(iListener.Bind(address));
User::LeaveIfError(iListener.Listen(5));
AcceptNextConnectionL();
AcceptNextConnectionL:
User::LeaveIfError(iblankSocket.Open(iServer));
iListener.Accept(iblankSocket, iStatus);
SetActive();
RunL:
if (iStatus.Int() == KErrNone) {
iblankSocket.RecvOneOrMore(iBuffer, 0, iStatus, iLength);
}
if (iStatus.Int() == KErrNone) {
ParseRequestL();
AcceptNextConnectionL();
}
ParseRequest parses my http-request, and if a (simple in this case)
.html-file is requested, the following function is called:
HBufC* uri = HBufC::NewL(aURI.Length());
TPtr uriPtr = uri->Des();
uriPtr.Copy(aURI);
CleanupStack::PushL(uri);
TFileName fileName(KSrcHTML);
fileName.Append(uri->Mid(1));
HBufC* file_path = fileName.AllocL();
CleanupStack::PushL(file_path);
CleanupStack::PopAndDestroy(2);
if (BaflUtils::FileExists(iFs, *file_path)) {
User::LeaveIfError(iFile.Open(iFs, *file_path, EFileShareReadersOnly |
EFileRead));
HBufC8* buffer = HBufC8::NewL(4000);
TPtr8 bufferPtr = buffer->Des();
bufferPtr.Copy(KStatus);
TInt s;
iFile.Size(s);
bufferPtr.Append(KContentLength);
bufferPtr.Append(s);
bufferPtr.Append(KCRLF8);
bufferPtr.Append(KContentType);
bufferPtr.Append(KHTMLContent);
bufferPtr.Append(KCRLF8);
bufferPtr.Append(KCRLF8); //empty row
HBufC8* fileBuffer = HBufC8::NewL(s);
TPtr8 filePointer = fileBuffer->Des();
User::LeaveIfError(iFile.Read(filePointer));
bufferPtr.Append(filePointer);
TRequestStatus iStatus;
iblankSocket.Write(*buffer, iStatus);
iblankSocket.Close();
iFile.Close();
Well, reading the request (RecvOneOrMore) just works fine - I get the right
"string".
But as soon as I click on a link of my page in the browser, requesting a
page from my server, the server crashes... I don't see what the problem is.
Maybe it's not that good to have the RSocket blank-socket as a
member-variable? It's right to open and close the (same) socket for every
connection, isn't it? When using the active-object-concept, it can't be that
the server just "stops" when i close the blank-socket?
Hopefully anyone can help me, I'm quite stuck...
Thanks in advance
Ronald
|
| Post Reply
|
| Re: Sockets again... |
 |
16 Feb 2006 21:15:50 +0200 |
"Ronald Petrlic" <petrlic@gmx.at> writes:
> Dear Symbian-Developers,
>
> I've got the following problem: My Symbian-web-server just doesn't work as
> it should...
> As mentioned in other tutorials, I'm doing the following:
>
> //member-vars:
> RSocket iListener;
> RSocketServ iServer;
> RSocket iblankSocket;
> TBuf8<1000> iBuffer;
> RFile iFile;
>
> User::LeaveIfError(iServer.Connect(2));
> User::LeaveIfError(iFs.Connect());
> TInetAddr address(KInetAddrLoop, 80);
> User::LeaveIfError(iListener.Open(iServer, KAfInet, KSockStream,
> KProtocolInetTcp));
> User::LeaveIfError(iListener.Bind(address));
> User::LeaveIfError(iListener.Listen(5));
> AcceptNextConnectionL();
>
> AcceptNextConnectionL:
> User::LeaveIfError(iblankSocket.Open(iServer));
> iListener.Accept(iblankSocket, iStatus);
> SetActive();
How does your RunL know whether it's being called because Accept
completed or RecvOneOrMore completed? You need a state variable, say
after Accept:
iState = EAccept;
>
> RunL:
> if (iStatus.Int() == KErrNone) {
> iblankSocket.RecvOneOrMore(iBuffer, 0, iStatus, iLength);
> }
> if (iStatus.Int() == KErrNone) {
> ParseRequestL();
> AcceptNextConnectionL();
> }
Above is not working. Your RunL gets called on Accept completion. Then
you issue RecvOneOrMore, which may complete at once (if data has been
received) or not. The correct RunL should be
if (iStatus.Int() != KErrNone)
{
// Something is wrong, just abort serving this connection.
iblankSocket.Close();
AcceptNextConnectionL();
}
else if (iState == EAccept)
{
iblankSocket.RecvOneOrMore(iBuffer, 0, iStatus, iLength);
iState = EReading;
SetActive();
}
else if (iState == EReading)
{
// Except you never know whether you read has received all
// of the request. RecvOneOrMore may return 1 byte. But,
// that's for you to redesign your application... (you really need
// to keep reading and buffering until your request is completely
// received, and only then call parse...)
ParseRequestL();
AcceptNextConnectionL();
}
else if (iState == EWriting)
{
iblankSocket.Close();
AcceptNextConnectionL();
}
return;
> ParseRequest parses my http-request, and if a (simple in this case)
> .html-file is requested, the following function is called:
> HBufC* uri = HBufC::NewL(aURI.Length());
> TPtr uriPtr = uri->Des();
> uriPtr.Copy(aURI);
>
> CleanupStack::PushL(uri);
> TFileName fileName(KSrcHTML);
> fileName.Append(uri->Mid(1));
> HBufC* file_path = fileName.AllocL();
> CleanupStack::PushL(file_path);
>
> CleanupStack::PopAndDestroy(2);
Ugh.. in above you are destroying your "file_path", all bets are off
when you use it below..
> if (BaflUtils::FileExists(iFs, *file_path)) {
> User::LeaveIfError(iFile.Open(iFs, *file_path, EFileShareReadersOnly |
> EFileRead));
>
> HBufC8* buffer = HBufC8::NewL(4000);
> TPtr8 bufferPtr = buffer->Des();
>
> bufferPtr.Copy(KStatus);
>
> TInt s;
> iFile.Size(s);
>
> bufferPtr.Append(KContentLength);
> bufferPtr.Append(s);
> bufferPtr.Append(KCRLF8);
> bufferPtr.Append(KContentType);
> bufferPtr.Append(KHTMLContent);
> bufferPtr.Append(KCRLF8);
> bufferPtr.Append(KCRLF8); //empty row
> HBufC8* fileBuffer = HBufC8::NewL(s);
> TPtr8 filePointer = fileBuffer->Des();
> User::LeaveIfError(iFile.Read(filePointer));
>
> bufferPtr.Append(filePointer);
>
> // TRequestStatus iStatus; <--- bad!
NO! You cannot declare your local iStatus for active object. Use the
one in Active object!
> iblankSocket.Write(*buffer, iStatus);
iState = EWriting;
SetActive();
>
>/// iblankSocket.Close(); <-- do not close!
>
> iFile.Close();
Your "fileBuffer" and "buffer" are never released? Anyway,
you cannot
release/resuse the buffer until Write completes in the RunL. Thus, you
need to put buffer in to member variable! (probably allocate it
permanently and reuse the same buffer again, with possible resize, if
needed).
|
| Post Reply
|
| Re: Sockets again... |
 |
Tue, 21 Feb 2006 11:00:56 +010 |
Wow, thank you very much for your answer. It really helped me - now my
server is working...
I think I got the conecpt of "cooperative multitasking" with active
objects
now, and I must admit that it isn't that bad I had thought at the
beginning...
Best regards,
Ronald
"Markku Savela" <msa@moth.iki.fi> schrieb im Newsbeitrag
news:87accr9kt5.fsf@burp.tkv.asdf.org...
> "Ronald Petrlic" <petrlic@gmx.at> writes:
>
>> Dear Symbian-Developers,
>>
>> I've got the following problem: My Symbian-web-server just doesn't work
>> as
>> it should...
>> As mentioned in other tutorials, I'm doing the following:
>>
>> //member-vars:
>> RSocket iListener;
>> RSocketServ iServer;
>> RSocket iblankSocket;
>> TBuf8<1000> iBuffer;
>> RFile iFile;
>>
>> User::LeaveIfError(iServer.Connect(2));
>> User::LeaveIfError(iFs.Connect());
>> TInetAddr address(KInetAddrLoop, 80);
>> User::LeaveIfError(iListener.Open(iServer, KAfInet, KSockStream,
>> KProtocolInetTcp));
>> User::LeaveIfError(iListener.Bind(address));
>> User::LeaveIfError(iListener.Listen(5));
>> AcceptNextConnectionL();
>>
>> AcceptNextConnectionL:
>> User::LeaveIfError(iblankSocket.Open(iServer));
>> iListener.Accept(iblankSocket, iStatus);
>> SetActive();
>
> How does your RunL know whether it's being called because Accept
> completed or RecvOneOrMore completed? You need a state variable, say
> after Accept:
>
> iState = EAccept;
>
>
>>
>> RunL:
>> if (iStatus.Int() == KErrNone) {
>> iblankSocket.RecvOneOrMore(iBuffer, 0, iStatus, iLength);
>> }
>> if (iStatus.Int() == KErrNone) {
>> ParseRequestL();
>> AcceptNextConnectionL();
>> }
>
> Above is not working. Your RunL gets called on Accept completion. Then
> you issue RecvOneOrMore, which may complete at once (if data has been
> received) or not. The correct RunL should be
>
> if (iStatus.Int() != KErrNone)
> {
> // Something is wrong, just abort serving this connection.
> iblankSocket.Close();
> AcceptNextConnectionL();
> }
> else if (iState == EAccept)
> {
> iblankSocket.RecvOneOrMore(iBuffer, 0, iStatus, iLength);
> iState = EReading;
> SetActive();
> }
> else if (iState == EReading)
> {
> // Except you never know whether you read has received all
> // of the request. RecvOneOrMore may return 1 byte. But,
> // that's for you to redesign your application... (you really need
> // to keep reading and buffering until your request is completely
> // received, and only then call parse...)
> ParseRequestL();
> AcceptNextConnectionL();
> }
> else if (iState == EWriting)
> {
> iblankSocket.Close();
> AcceptNextConnectionL();
> }
> return;
>
>> ParseRequest parses my http-request, and if a (simple in this case)
>> .html-file is requested, the following function is called:
>> HBufC* uri = HBufC::NewL(aURI.Length());
>> TPtr uriPtr = uri->Des();
>> uriPtr.Copy(aURI);
>>
>> CleanupStack::PushL(uri);
>> TFileName fileName(KSrcHTML);
>> fileName.Append(uri->Mid(1));
>> HBufC* file_path = fileName.AllocL();
>> CleanupStack::PushL(file_path);
>>
>> CleanupStack::PopAndDestroy(2);
>
> Ugh.. in above you are destroying your "file_path", all bets are
off
> when you use it below..
>
>> if (BaflUtils::FileExists(iFs, *file_path)) {
>> User::LeaveIfError(iFile.Open(iFs, *file_path,
EFileShareReadersOnly
>> |
>> EFileRead));
>>
>> HBufC8* buffer = HBufC8::NewL(4000);
>> TPtr8 bufferPtr = buffer->Des();
>>
>> bufferPtr.Copy(KStatus);
>>
>> TInt s;
>> iFile.Size(s);
>>
>> bufferPtr.Append(KContentLength);
>> bufferPtr.Append(s);
>> bufferPtr.Append(KCRLF8);
>> bufferPtr.Append(KContentType);
>> bufferPtr.Append(KHTMLContent);
>> bufferPtr.Append(KCRLF8);
>> bufferPtr.Append(KCRLF8); //empty row
>> HBufC8* fileBuffer = HBufC8::NewL(s);
>> TPtr8 filePointer = fileBuffer->Des();
>> User::LeaveIfError(iFile.Read(filePointer));
>>
>> bufferPtr.Append(filePointer);
>>
>> // TRequestStatus iStatus; <--- bad!
>
> NO! You cannot declare your local iStatus for active object. Use the
> one in Active object!
>
>> iblankSocket.Write(*buffer, iStatus);
>
> iState = EWriting;
> SetActive();
>>
>>/// iblankSocket.Close(); <-- do not close!
>>
>> iFile.Close();
>
> Your "fileBuffer" and "buffer" are never released?
Anyway, you cannot
> release/resuse the buffer until Write completes in the RunL. Thus, you
> need to put buffer in to member variable! (probably allocate it
> permanently and reuse the same buffer again, with possible resize, if
> needed).
>
>
>
>
>
>
|
| Post Reply
|
|
|