Simultaneously reading and writing over a socket

One more thing that just hit me. PacketWriter synchronizes on its queue and PacketReader on its (vector of) listeners, connectionListeners, connectionIDLock, collectors. Should maybe any of these synchronize on the connection instead as well?

Probably is since it’‘s part of the CLDC/MIDP API. I’'m not >sure if we want to go there though.

No, I was looking at a the J2SE implementation.

This might indeed work, although it’'s getting more

cumbersome than I expected in the beginning.

Yeah, me too That’‘s what I meant with “I am in a hurry.” If I would’'ve thought it over more thoroughly I would have known this before hand

One more thing that just hit me. PacketWriter

synchronizes on its queue and PacketReader on its (vector

of) listeners, connectionListeners, connectionIDLock,

collectors. Should maybe any of these synchronize on the >connection instead as well?

Not sure, but I don’'t think so. We just want to synchronize on the most atomar level possible, which is the connection. This is the only thing we need to take care of, as we “only” try to protect the connection from simultanous access.

At least that is what I can think of at the moment.

Cheers,

Mariano

ps. No clue, what I could answer in dutch Go Oranje Go!

Hi Berco,

I implemented a synchronized writer, which was pretty simple.

http://www.jabberstudio.org/cgi-bin/viewcvs.cgi/pepemax/pepemax/Scratchpad/src/b erco/SynchronizedWriter.java?view=markup

or

http://tinyurl.com/32pzl

A reader with the approach we discussed, i.e. doing the reading in a different Thread. That wasn’'t so simple.

http://www.jabberstudio.org/cgi-bin/viewcvs.cgi/pepemax/pepemax/Scratchpad/src/b erco/SynchronizedReader.java?view=markup

or

http://tinyurl.com/ypmqr

And a testcase, which failed with the last approach, but succeeded with this approach.

http://www.jabberstudio.org/cgi-bin/viewcvs.cgi/pepemax/pepemax/Scratchpad/src/b erco/Test.java?view=markup

or

http://tinyurl.com/33f4c

That is probably not the end, but a step forward

Cheers,

Mariano

ps. I really don’'t have any idea why the links are messed up when rendered, but of course, you need to concatenate the parts to get a full url ;-(

Message was edited by: mariano

Added tiny urls.

Hi Mariano,

Impressive! Again, thanks for all the effort. Unfortunately the app still hangs when calling:

eventType = parser.next();

in PacketReader.parsePackets().

Summing up what I did is:

  1. PacketReader.

parser.setInput(new SynchronizedReader(connection.reader, connection));

  1. PacketWriter.

this.writer = new SynchronizedWriter(connection.writer, connection);

And in PacketWriter.writePackets() made sure that all writing appeared within synchronized blocks as in the following example:

synchronized(connection) {

writer.write(“abc”);

writer.flush();

connection.notifyAll();

}

  1. SynchronizedReader.

Commented out

readingThread.setName(“Reading Thread”);

since that method is not available in J2ME.

It might very well be that I’'m not using your classes correctly.

Cheers,

Berco

Hi Berco,

Unfortunately the app still hangs when calling:

That seems to be the recurring theme here ;-(

eventType = parser.next();

in PacketReader.parsePackets().

Not sure with what code you’'re working.

Anyway. Can you isolate it and make it a test case? One that runs with J2SE?

Summing up what I did is:

That’'s all fine.

You removed the other synchronisations we introduced, right?

And in PacketWriter.writePackets() made sure that all

writing appeared within synchronized blocks as in the

following example:

synchronized(connection) {

writer.write(“abc”);

writer.flush();

connection.notifyAll();

}

Not sure if that makes any difference, but no, that is not necessary anymore. The synchronisation is now done in the reader and writer.

Commented out

readingThread.setName(“Reading Thread”);

since that method is not available in J2ME.

Pls let’‘s get this thing get up and running in J2SE and then we’'ll see about J2ME.

It might very well be that I’'m not using your classes

correctly.

No, I believe you do. Anyway, we need a small, isolated, testcase, that I can work on. Like the one I provided, but one that fails

Btw. mine failed with the original approach, but does work with the current approach. That does make me somewhat more confident, that the original problem is solvable.

Cheers,

Mariano

Berco,

bad news. I just talked to a co-worker of mine. He pointed out that my approach wouldn’‘t cover the original problem of not accessing the connection simultanously for read and write. The approach just makes sure that smack is not accessing the connection simultanously for read and write, but the ReadingThread does constantly read and I don’'t have a clue how to overcome this.

Sorry.

Btw. why does MIDP not allow to simultanously access the streams? Have you got a link handy? What happens if you violate this constraint? What does the error message say?

Cheers,

Mariano

Hi Mariano,

Major bugger!

The reading is indeed constantly done…

It’‘s not MIDP that doesn’‘t allow this but the specific implementation of MIDP. It’‘s for instance not supported on the SonyEricsson P900. You can find that information in SE’'s dev department:

http://developer.sonyericsson.com/

I’'ll revert the code back to the original state and get back with any additional information I can get.

Thanks again for now.

Cheers,

Berco

Hi Berco,

http://developer.sonyericsson.com/

Have you got a more specific link?

Currently I only see 2.5 more ways to solve this:

a) The main problem is that currently a blocking api is employed by smack. Changing that to the NIO would work, but is

  1. a major rework of the network stuff of smack - possible

  2. likely not compatible with the xmpull-api - makes it even more work

  3. likely not available on j2me, is it? - bugger

Anyway. There is JSO out there, which also provides a jabber API on a lower level. The upside is, that they do use NIO. Not sure though, how much of it they expose.

If J2ME supports NIO it might be worth to give it a shot at the developer’'s mailing list.

http://jso.jabberstudio.org/

b) Implement a proxy. If you would run a proxy on the server side, it could provide you with a request/response protocoll. As a result it would mean that you need to poll for new information.

c) Use timeouts

I am not aware if this is possible at all, but if it would be possible to unblock a blocking read after a certain amount of time, this should also work, but would probably not be very responsive, but this also holds true for b).

How do other people overcome these kinds of problems?

Whatever way you chose, I’‘d like to pull myself away from it. At least for the time being. My spare time is pretty limited and I’'d like to focus on an eclipse jabber plugin.

I am happy to come back to this topic at a later date, but right now … ;-(

Sorry, for not being more of a help to you.

Cheers,

Mariano

Hi Mariano,

Have you got a more specific link?

http://developer.sonyericsson.com/viewSolution.do?id=5332

It says:

"Why can’'t I read and write to a socket connection at the same time using Java on P800?

This is a KVM socket limitation in P800. You can’‘t write to a socket connection while there’'s a blocked read on that socket (the read and write operations share a buffer). This is not a limitation with http:// because the socket operations are sequential: write then read, write then read, and so on. Both of the mentioned MIDlets appear to start a dedicated thread for reading data from a socket, and then (while the read is blocked) try to write commands down the socket from another thread. The way socket:// is implemented, the write is locked out of trying to grab a lock that the blocked read operation holds, and so never completes. If the write happens on the UI thread, this will wedge the UI. Note that socket:// is not a mandatory protocol to support in order to reach TCK certification, it is an optional feature implemented on some KVM implementations. This is a limitation in the Symbian implementation that developers need to be aware of in order to avoid problems with socket read/write operations."

Mind you, it’‘s not just this phone that doesn’'t support duplex sockets.

Currently I only see 2.5 more ways to solve this:

a) The main problem is that currently a blocking api

is employed by smack. Changing that to the NIO would

work, but is

  1. a major rework of the network stuff of smack -
  • possible
  1. likely not compatible with the xmpull-api - makes

s it even more work

  1. likely not available on j2me, is it? - bugger

Anyway. There is JSO out there, which also provides a

jabber API on a lower level. The upside is, that they

do use NIO. Not sure though, how much of it they

expose.

If J2ME supports NIO it might be worth to give it a

shot at the developer’'s mailing list.

http://jso.jabberstudio.org/

NIO is not a part of J2ME, so that is unfortunately a no go.

b) Implement a proxy. If you would run a proxy on the

server side, it could provide you with a

request/response protocoll. As a result it would mean

that you need to poll for new information.

c) Use timeouts

I am not aware if this is possible at all, but if it

would be possible to unblock a blocking read after a

certain amount of time, this should also work, but

would probably not be very responsive, but this also

holds true for b).

I guess that using timeouts is the way to go. It’'s not very elegant, but apparently the only solution.

How do other people overcome these kinds of

problems?

They don’'t. HTTP was usually the network protocol used on mobile terminals, and that is sequential by nature. Since sockets will be standard in MIDP2 I expect many more developers to run into this same limitation.

Whatever way you chose, I’'d like to pull myself away

from it. At least for the time being.

That is very understandable, Mariano. You’'ve been a tremendous help for me and there is a time to give up when there is no solution.

My spare time

is pretty limited and I’'d like to focus on an eclipse

jabber plugin.

Wow! IM from within eclipse? That would be neat!

I am happy to come back to this topic at a later

date, but right now … ;-(

I’‘ll continue my quest, this time by doing some hacking with timeouts. I’‘ll let you know when I’‘ve got something. Anyways, it’‘s a pity to find out that SMACK is unportable to J2ME since that is a very large future market if you ask me. Besides, it’‘s rather frustrating for me to finally have ported the complete SMACK API, have it running on a terminal and finally finding out it won’‘t work on a real phone. That’‘s like a marathon runner that breaks down 2 meters in front of the finish I’'ll post my findings to the list anyway.

Anyway, thanks again for all your help. I really appreciate that.

Cheers,

Berco

Message was edited by: berco

Added the text from the url