Let\'s say Java has two kind of sockets:
Imagine the situation of two
In C you can call socketpair(2) to get a pair of connected sockets, but I'm not sure if java has any built-in way of doing the same thing.
If you want a peer-to-peer
connection you might want to consider using UDP
.
UDP
can receive from anything without establishing a connection first, you will still need a server to tell the clients who they're receiving data from though.
Hope this helped.
Generally speaking, a client TCP socket has two ends (local and “remote”) and a server TCP socket has one end (because it is waiting for a client to connect to it). When a client connects to the server, the server internally spawns a client socket to form connected pair of client sockets that represent the communications channel; it's a pair because each socket views the channel from one end. This is How TCP Works (at a high level).
You can't have two client sockets connect to each other in TCP, as the low-level connection protocol doesn't work that way. (You can have a connected pair of sockets created that way in Unix, but it's not exposed in Java and they're not TCP sockets.) What you can do is close the server socket once you've accepted a connection; for simple cases, that might be good enough.
UDP sockets are different, of course, but they work with datagrams and not streams. That's a very different model of communication.
The ServerSocket allows you to listen for connections on a particular port. When a server socket accepts a connection, it spawns another thread, and moves the connection to another port, so the original port can still listen for additional connections.
The client initiates the connection on the known port. Then, typically, the client will send some request, and the server will respond. This will repeat until the communication is complete. This is the simple client/server approach that the web uses.
If you don't need this mechanism, and requests may come from either socket at any time, then implementing the reader and writer threads the way you have seems appropriate.
Internally, they still use wait mechanisms, so you shouldn't see much CPU usage while they wait for data to arrive.
I think you still need one end to be a server socket because I don't think it's possible to have a client socket accept a connection. ClientSocket implies TCP, which requires a connection. If you used DatagramSocket, which implies UDP, you could have client to client communication, without a connection.
Are you trying to created a mocked socket ? If so, mocking both sides of the pipe may be a bit more complicated than necessary.
On the other hand, if you just want to create a data pipe between two threads, you could use PipedInputStream and PipedOutputStream.
However, without more information about what your trying to accomplish, I cannot tell you if either of these choices is a good fit or if something else would be better.
A socket
(in networking terms) consists of 2 endpoints (The client and the server app) and 2 streams
. The output stream of the client is the input stream of the server and vice versa.
Now try to imagine what happens if a thread writes a lot of data to a stream while no one reads... There are buffers, true, but they aren't unlimited and they can vary in size. In the end your writing thread will hit the limit of the buffer and will block until someone frees the buffer.
Having said that, you should now be aware that this will need at least two different threads per Stream: one that writes and one that reads the written bytes.
If your protocol is request-response style, you could stick with 2 threads per socket, but no less.
You could try to replace the networking part of your application. Just create an abstract interface where you can hide the whole networking part, like:
interface MyCommunicator{
public void send(MyObject object);
public void addReader(MyReader reader);
}
interface MyReader{ //See Observer Pattern for more details
public void received(MyObject object);
}
This way you could easily remove the whole networking (including en- & decoding of your objects, etc) and minimize threading.
If you want the data binary, you could use pipes instead or implement your own streams to prevent threading. The business or processing logic should not know about sockets, streams are low-level enough and maybe too much.
But either way: Threading isn't bad, as long as you don't overuse it.