Splitting a full-duplex socket

C

Chris Uppal

cyberco said:
Still no solution.... Anybody any tips?

Maybe it would help clarify what you are looking for if you'd explain in what
way the obvious solution is inapplicable. I.e. the client opens two
connections to the proxy server (different ports), one for reading, the other
for writing; the proxy server responds by opening one (normal, full-duplex)
connection to the real server, and thereafter just copies everything through.

-- chris
 
S

Steve Horsley

Sudsy said:
Incomplete problem description could be the difficulty. Some of what
you've posted makes no sense. A Berkeley socket is, by definition,
bidirectional. If you're using a platform which doesn't implement the
basic (expected) functionality then you'd be better served going back
to the provider.
Perhaps the lack of response is due to incomprehensibility of the
stated problem.

Certainly, I confirm that I have dropped out because I cannot
understand how a socket could "not support full duplex". It
seems to me that the answer to this is "In that case, it's
NOT a socket.", and you are dealing with an API of which I
know nothing.

Steve
 
C

cyberco

OK, sorry for not being any clearer in my problem description and sorry
for not replying with inline quotes (the reason for the latter is that
I'm using the new 'Google groups' which doesn't have an option to quote
the original post. For those replying that they don't know of any
sockets that are *not* full-duplex: check out J2ME enabled phones, most
of them DO NOT support full-duplex sockets. And its not just obscure
models. SonyErisscon, NOKIA, Motorola etc.

As for the problem, Chris got it right:
the client opens two
connections to the proxy server (different ports), one for reading, the other
for writing; the proxy server responds by opening one (normal, full-duplex)
connection to the real server, and thereafter just copies everything
through.

That's what I want to do, and I guess my simple question is how to do
the copying.

Cheers,
cyberco
 
C

cyberco

OK, sorry for not being any clearer in my problem description and sorry
for not replying with inline quotes (the reason for the latter is that
I'm using the new 'Google groups' which doesn't have an option to quote
the original post. For those replying that they don't know of any
sockets that are *not* full-duplex: check out J2ME enabled phones, most
of them DO NOT support full-duplex sockets. And its not just obscure
models. SonyErisscon, NOKIA, Motorola etc.

As for the problem, Chris got it right:
the client opens two
connections to the proxy server (different ports), one for reading, the other
for writing; the proxy server responds by opening one (normal, full-duplex)
connection to the real server, and thereafter just copies everything
through.

That's what I want to do, and I guess my simple question is how to do
the copying.

Cheers,
cyberco
 
J

John C. Bollinger

cyberco said:
As for the problem, Chris got it right:



the other


through.

That's what I want to do, and I guess my simple question is how to do
the copying.

Surely there must be some parameters, caveats, constraints, provisos, or
something? What's hard about reading bytes from an InputStream and
writing them to an OutputStream?

There seems to be some kind of disconnect here. Have you tried to write
something and run into trouble? I think the reason so many of us are
having trouble answering the question is that we don't understand why
you're having any problem with the code in the first place.


John Bollinger
(e-mail address removed)
 
S

Steve Horsley

cyberco said:
OK, sorry for not being any clearer in my problem description and sorry
for not replying with inline quotes (the reason for the latter is that
I'm using the new 'Google groups' which doesn't have an option to quote
the original post. For those replying that they don't know of any
sockets that are *not* full-duplex: check out J2ME enabled phones, most
of them DO NOT support full-duplex sockets. And its not just obscure
models. SonyErisscon, NOKIA, Motorola etc.
Is there a web site documenting this? It throws everything I ever learned
about sockets.
As for the problem, Chris got it right:



the other


through.

That's what I want to do, and I guess my simple question is how to do
the copying.

Here's one I wrote earlier...

public class RelayHelper implements Runnable {

private InputStream in;
private OutputStream out;

public RelayHelper(InputStream in, OutputStream out) {
this.in = in;
this.out = out;
}

/** Copy from in to out until EOF. */
public void run() {
Thread.currentThread().setName("RelayHelper");
try {
byte[] buf = new byte[1600];
while(true) {
int len = in.read(buf);
if(len == -1) { //EOF - cnx closed
break;
}
out.write(buf, 0, len);
out.flush();
}
} catch(Exception ex) {
//ex.printStackTrace();
} finally {
try {
in.close();
} catch(Exception ex) {
}
try {
out.close();
} catch(Exception ex) {
}
}
}
}


Use it like this:

RelayHelper rh1 = new RelayHelper(hostIn, clientOut);
RelayHelper rh2 = new RelayHelper(clientIn, hostOut);
new Thread(rh1).start();
// loop forwarding data
rh2.run();


This uses one thread to copy data in each direction. Using NIO, you
could get away with one thread and select().

Your problem is the logic behind figuring out which incoming
connectons are from the same client and therefore need to be treated
as a read/write pair. Maybe assume that one client IP will only ever
want one connection pair, then keep a list of connections that have
arrived on ServerSocket A and try and match them with connections on
ServerSocket B (using Socket.getAddress()), opening a socket to the
host when you find a matching pair, and then launching a pair of
RelayHelpers to do the relaying.

HTH

Steve
 
C

cyberco

Boy...this discussion somehow got out of hand!
Surely there must be some parameters, caveats, constraints, provisos, or
something? What's hard about reading bytes from an InputStream and
writing them to an OutputStream?

Nope. My initial idea was to create a proxy that does just that.
There seems to be some kind of disconnect here. Have you tried to write
something and run into trouble? I think the reason so many of us are
having trouble answering the question is that we don't understand why
you're having any problem with the code in the first place.

I did (and still do) not know whether that simple solution would work
and what the optimal solution would be (should I simply use an
InputStream? Or a ByteArrayInputStream? How many bytes should I read?
Etcetera.) That's why I asked for some advice here. But to illustrate
what my situation was I said that I needed it for a mobile phone that
doesn't support full-duplex sockets to communicate with a server-side
application that ONLY accepts full-duplex sockets. That got most of the
responders off into the wrong direction. Many got confused by reading
about devices not supporting full-duplex sockets.

Anyway, in the meantime I implemented a proxy that reads and forwards
characters (using seperate threads). It seems to work inside the proxy,
but it might not be an optimal solution :( The client side still
doesn't work though. I'll keep debugging.
I apologize to everybody here I might have confused.

Cheers,
Berco
 
R

Rene

cyberco said:
I did (and still do) not know whether that simple solution would work
and what the optimal solution would be (should I simply use an
InputStream? Or a ByteArrayInputStream? How many bytes should I read?
Etcetera.) That's why I asked for some advice here. But to illustrate
what my situation was I said that I needed it for a mobile phone that
doesn't support full-duplex sockets to communicate with a server-side
application that ONLY accepts full-duplex sockets. That got most of the
responders off into the wrong direction. Many got confused by reading
about devices not supporting full-duplex sockets.

Anyway, in the meantime I implemented a proxy that reads and forwards
characters (using seperate threads). It seems to work inside the proxy,
but it might not be an optimal solution :( The client side still
doesn't work though. I'll keep debugging.
I apologize to everybody here I might have confused.

And which mobile phone would that be? I still am very confused about this
specific problem of yours. I've been working in the network area for over
10 years and programming for a bit over 5 years in that field. I've never
ever seen anything like that. You can do some really weird stuff, for
example using raw sockets or with multicast, but I've yet to see a one way
TCP or UDP socket.

If you give a bit more (technical) details, some test-code that encompasses
the problem for example, we might help, but as for now, confusion still
reigns. At least from my side.

If you cannot give code because that's your commercial project, strip it
down to some dummy code that does nothing useful except to show the
problem. But without seeing any code or getting more useful information, I
really doubt that you get useful information back from here. You know,
garbage in, garbage out.

CU

Rene
 
C

Chris Uppal

Steve said:
Your problem is the logic behind figuring out which incoming
connectons are from the same client and therefore need to be treated
as a read/write pair. Maybe assume that one client IP will only ever
want one connection pair, then keep a list of connections that have
arrived on ServerSocket A and try and match them with connections on
ServerSocket B (using Socket.getAddress()), opening a socket to the
host when you find a matching pair, and then launching a pair of
RelayHelpers to do the relaying.

That's how I would approach this too. However I'd want to be a bit more
careful about closing the sockets. The proxy should be able to "copy" closure
of the streams using the "half-close" operations on the server connection
(close-for-reading-but-not-for-writing, and the reverse).

Also, I'd consider using nio to avoid the need for twice as many threads as
client connections. But I doubt if I'd bother thinking about that until after
I'd got a simple threaded implementation working.

-- chris
 
S

Steve Horsley

Chris said:
Steve Horsley wrote:
That's how I would approach this too. However I'd want to be a bit more
careful about closing the sockets. The proxy should be able to "copy" closure
of the streams using the "half-close" operations on the server connection
(close-for-reading-but-not-for-writing, and the reverse).
You are right. That code was used for relaying between two bidirectional
sockets as a simple telnet proxy where direct routing was not possible.
When dealing with three entangled sockets, closing things does need rather
more care.

Steve
 
R

Rene

cyberco said:


Uh is that your site? I'm asking because it does not look very
authoritative on the problem at hand. It says that it will work on the
Nokia but not on the Sony Ericsson P900.

I think I know now what you are trying to say. On J2ME, it is not mandatory
under the MIDLET 1 specification to provide the Socket class for arbitrary
sockets. However it is mandatory to support HTTP-Connections. So in order
to circumvent this limitation you create a HTTP proxy which takes this
HTTP-Connection from the phone, create a normal socket on the proxy etc.

What you were baffling us all with if I see this scenario correct is simply
that this HTTP connection *is* full duplex, however you cannot access and
use it in the same way as a normal socket. Full duplex means you can send
and receicve and HTTP absolutely requires this (send header, receive
result). But you kept saying you had no Full-duplex connection, which is
quite simply wrong - and very puzzling too. It would mean you could only
send or receive per connection, so that you would need two connections for
full-duplex on the phone. And I'm pretty sure that this is not the case.

MIDP2 defines socket which is probably what you'd like to have. But if not,
and MIDP1 does not define them, then some sort of application proxy on a
WAP-gateway is the way to go. Never the less, what you're having is one
full-duplex socket, because you use it for reading from the phone and
writing data to the phone. It may be that you use several since HTTP is
stateless and generally does one connection per request ("send cycle", if
you want) but maybe you can force it in the non-closing mode where after a
request got sent it will not close the connection but stay open (NPH).
Don't know if the feature is there, I don't do MIDLETs. Anyway, back to the
original question: What is the best way to do it ? My answer is, it depends
a lot on the protocol on the other side of the proxy. It may be very easy
to map it onto the HTTP stream or damn difficult. What type of protocol is
there?

CU

Rene
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,130
Latest member
MitchellTe
Top