|
|
User login
Feeds |
Nokia 6600 BT Send needs delay
|
|||||
| Mon, 2004-11-29 11:53 | |
|
Hy everybody,
I've implemented, based on the PointToPoint example in the Series 60 SDK, a simple Bluetooth chat. Everything works just fine. The problem is that in such an application two sends are relatively deffered from one another (at least 1 sec). When I tried to modify the application and do something basicly simple, like making 10 repeated sends, everything breaks down. Here is what I do: CSender::StartSending() { iCount = 0; TPckg<TInt> countPckgDes(iCount); iClientSocket.Send(countPckgDes, 0, iStatus); SetActive(); } CSender::RunL() { if (iStatus == KErrDisconnected) { asyncBtCallBack.AppendToLogL(_L("Disconnected")); return; } else if (iStatus == KErrAbort) { asyncBtCallBack.AppendToLogL(_L("Aborted")); return; } else if (iStatus != KErrNone) { asyncBtCallBack.AppendToLogL(_L("Receiver Error")); return; } ++ iCount; if(iCount < 10) { TPckg<TInt> countPckgDes(iCount); iClientSocket.Send(countPckgDes, 0, iStatus); SetActive(); } } At the receiver end, I receive only the first 7 bytes and after that my phone server application, which is sending, gets killed. My guess is that RunL() gets called, not when the data was actually sent through the bluetooth radio, but when the data is copied in some bluetooth sending buffer, so i'm sending data a lot faster than the BT hardware can send. I'm sure of this, because if I do a small delay in RunL() before the next send, everything works fine. What should I do to solve this? I thought of 2 things, but I don't know exactly how to do it :1) can I somehow get the sending status from the clientSocket. I tried to poll it with the following code, but it didn't work: TInt socketOptionInt; TPckg<TInt> socketOptionPckgInt(socketOptionInt); clientSocket.GetOpt(KSOSelectPoll, KSOLSocket, socketOptionPckgInt); if( ! (socketOptionInt & KSockSelectWrite) ) { return; } Also iStatus is always KErrNone, so it doesn't help me. 2) I've seen in the API something about blocking sockets. I don't know exactly what they are, and I couldn't find in the SDK either, but could they mean that a send would return only after the data was actually sent? Also I don't know how this "blocking" sockets should behave with asynchronous ActiveObjects. I've found on the forums two similar posts: one about generic TCP/IP sockets, in which repetead sends blocked, and one about RecvOneOrMore() on BT sockets in Nokia 6600 which, like in my case, needed some delay to complete. Thanks a lot in advance |
|
Forum posts: 14
if(iCount < 10)
{
TPckg<TInt> countPckgDes(iCount);
iClientSocket.Send(countPckgDes, 0, iStatus);
SetActive();
}
into the iStatus != KErrNone part of RunL.
That's the part that gets called when the previous data has been sent without problems (and that means you don't need to guess some random delay).
Forum posts: 21
Forum posts: 14
Tried just using the RSocket::Write method instead of send to see if that makes any difference?
Now that i read the whole thing i'm at a loss on what the problem is. Probably something really small and simple yet so typically annoying to find.
If i were you, i'd just move things around (like the TPckg to be a class member), try out the RSocket::Write style etc. Sorry i can't be of more use.
Forum posts: 21
Forum posts: 21
Forum posts: 21
But anyway, I remember that I have seen lots of examples (in books and also in documents from Nokia) where sending was done in this way: just before Send wrap the data into some automatic TPckg object and pass it to the asynchronous (Send() in this case) method.
But if I am wrong, and this is a bad practice, please reply and let me know which is the "standard" way. Because I don't like that for every class member that I would pass to some async method I should also declare a corresponding TPkg member.
Forum posts: 85
I am not sure what btpoint2point example you looked at to create your application because the RunL() and SendMessageL() functions of that example are nothing like the ones you wrote in your original post.
The btpoint2point example uses RSocket::Write() to send the message. And I am not sure how you came up with TPckg since there is no such thing in the example... The example uses HBufC8* iMessage to construct the message...
Forum posts: 21
Very good !!! I bet you are also an expert on the helloworld example. Keep on the good job.
Forum posts: 85
TPckg does not own the data it is passed. It points to it. Therefore the fact that your TPckg object is an automatic one is OK. Even if it goes out of scope at the end of the if block, iClientSocket.Send should still be pointing at iCount not at the TPckg object itself.
The fact that making the TPckg object a class member solved your problem doesn't make any sense. It probably hid your problem somehow. Based on how TPckg works, you shouldn't have to make it a class member which is probably why you never see it used that way in books and documents.
Maybe you could try the () operator to return a reference to the object TPckg points to.
Like I said, I can't see how it is a bad practice although I can see that you have issues with being snarky which will get you nowhere in life.
Good luck!
Wrong! Wrong!
1) TPckg creates a descriptor pointing to data.
2) Socket Send passes a pointer to descriptor to socket server.
The TPckg going out of scope is definitely a big problem!
Forum posts: 85
Information on TPckg, TPckgC and TPckgBuf is kinda limited. Therefore, my understanding of it might be wrong, but what you are saying surely doesn't make sense. All the server wants is the pointer to the object so it can read/write to that object. If what you are suggesting was true, there would be useless, meaningless objects pointing to objects that already exist such as
iCount << TPckg << ServerSideobject
As you can see the TPckg indirection is redundant.
What TPckg does is create a type-safe pointer to the original object -iCount- and pass it to the server side. When you call Socket::Send, -not sure if this is true but- it probably creates its own pointer to point to iCount. In this case TPckg is just a messanger. It is not needed after Socket::Send is called. Even if TPckg object disappears after the Socket::Send call, that's OK since server already has the address of iCount at that point.
Then you might ask "Why do we use a middleman -TPckg- to pass a pointer to iCount?".. Well like I said, TPckg is type-safe, and that's just how Symbian wanted to do it.
What you are suggesting makes sense for a TPckgBuf object since TPckgBuf actually creates a copy of the original object. If TPckgBuf went out of scope, then that would be a problem.
I could be wrong, but this makes a lot more sense than what you are suggesting.
Thats the way it is, whether it makes sense or not.
Forum posts: 12
I have the same freaking problem as you do: when sending data very fast over bluetooth RSocket does not call RunL or return from User::WaitForRequest(). First I used Write function, now I use Send with the last parameter showing exactly how much data was sent (it always equals to the buffer size I pass to this function
One solution I found out for nokia 6600 is deviding all of your data on 100 bytes buffers and send them one by one - socket never stuck, but the speed cannot exceed 10kB/s. And... It didn't work on 6630, 'cause the last is twice faster. But it worked if I devided initial data on 40 bytes buffers. But it is a bullshit to do things like that
So, right now I'm out of ideas! I come to your initial idea to put a sleep after sending some amount of data - but with this one still will come to 10kB/s speed (with the maximum of 60-100kB/s that I've reached on 6600). So, no difference if you devide packets manually or put a delay - both suck!
If anyone from Symbian or Nokia reads this, plzzzz, tell us all how we should work with RSocket and Bluetooth?
Thank you for your time
!
Vigen
Forum posts: 21
After some time I have discovered 3 main problems with Bluetooth on my Nokia 6600:
1) Send() doesn't quite work with automatic TPckgs, although here I agree with e_dawg that it should work, but anyway one could always use member TPckgs and get around this.
2) Asynchronous Send() is strange: if I pass packets bigger than 512 bytes, after some time Send() hangs, and RunL() doesn't get called. So perhaps there is a maximum limitation on the size of the packages that BT can handle (if anyone knows how to get this constant, pls reply
3) The last problem is very strange and has to deal more with AO I believe. Thus, in the following code:
++ iCount;
if(iCount < 10)
{
// iPckgdCount refers to iCount
iClientSocket.Send(iPckgdCount, 0, iStatus);
SetActive();
// ++ iCount;
}
1
2
2
4
5
5
7
... etc
So it looks like a race condition between ++ iCount and RunL(). But as I understand AO and Symbian, I have "cooperative multitasking", so I can not get preempted not even by RunL(), am I right? Perhaps I'm not, especially since in every code examples the asynchronous method call followed by SetActive() are the last code in every method.
Forum posts: 12
512 bytes were also too big for me (i don't know why
And one more thing: laptop client recieves the data by 666 (freaking number!!!!!) bytes everytime. So, I guess, the maximum you can send at once without stucking the bluetooth is 666 byte. So, your number - 512 - is in the allowed range.
Vigen