Java Socket/P2P questions - java

I'm learning about java sockets in a class of mine. I'm having issues with the communication between the peers. My question is why am I receiving this exception:
Exception java.net.ConnectionException: Connection refused: connect
for example:
in my main thread
ServerSocket listenSock = new ServerSocket(Integer.parseInt(argv[2]),0,InetAddress,getByName(null));
//Create Server loop to process inbound connections
while(true){
//accept an incoming client by saving it to a socket to use to communicate with it
Socket clientSock = listenSock.accept();
/waa/create a thread to handle the inbound client so that we can return to accept()
InboundHandler inboundMsg = new InboundHandler(clientSock); // listens to the peers outbound socket
Thread inThread = new Thread(inboundMsg);
inThread.start();
// add the peer to the list.
}
in a seperate thread I have a
public InboundHandler(Socket socket) throws Exception{
this.socket = socket; //save the socket object to "this" instance of the class
input = new BufferedReader(new InputStreamReader(socket.getInputStream())); // listens from the clients speaking socket
}
public void run(){
while(true){
try{
String line = input.readLine();
System.out.println(line);
}catch(IOException e){
System.out.println("Could not read input. " + e);
}
}
and finally I have a thread that sends out messages
for(int i=0;i<portList.size(); i++){
if(nameList.get(i)!=Username){
Socket peerSocket= new Socket(InetAddress.getByName(null),portList.get(i));
writer = new BufferedWriter(new OutputStreamWriter(peerSocket.getOutputStream()));
writer.write(Username + " has connected");
writer.flush();
}
}
}
catch(IOException e){
System.out.println("Some IO problem. " + e);
}
My program compiles, and when I run it, I receive the Exception
java.net.ConnectionException: Connection refused: connect
From what it's sounding like, is the port that my one peer is trying to speak to, isn't being heard by the other peers. But this is more guessing
As for the while(true) I am going to change that later, with a boolean statement.

Related

Strange behaviour of ServerSocket.accept method

I created class SocketListener to receive data through TCP protocol. My start method looks like this:
public void start() throws IOException {
LOGGER.log(Level.INFO, "SOCKET LISTENER STARTED PORT: " + port);
serverSocket = new ServerSocket(port);
while (true) {
FrameParser fp;
try {
socket = serverSocket.accept();
fp = new FrameParser(socket);
Thread thread = new Thread(fp);
thread.start();
} catch (Exception e) {
resetConnection();
}
}
}
Writing this code I based on example from oracle website (http://www.oracle.com/technetwork/java/socket-140484.html#server). When I placed line with serverSocket.accept() inside loop some of the packets was not received by ServerSocket. I am sure that this TCP packets was received on my network interface bacause I checked it later using Wireshark. I have no idea what causes that problem so I tried different things and I noticed that more packets was received when I change my code like this:
public void start() throws IOException {
LOGGER.log(Level.INFO, "SOCKET LISTENER STARTED PORT: " + port);
serverSocket = new ServerSocket(port);
socket = serverSocket.accept();
while (true) {
FrameParser fp;
try {
fp = new FrameParser(socket);
Thread thread = new Thread(fp);
thread.start();
} catch (Exception e) {
resetConnection();
}
}
}
I made this modification using trial and error method and unfortunately after this change my application started receive more data than I filtered in Wireshark (for example in Wireshark I saw 10 packets but my application created hundreds of new threads and it finished with out of memory error).
What can be a reason that in a first case not all of TCP packets reached to socket?

No response from second client socket

I am working with Java sockets. I have a server socket and two client sockets. My problem is, that the first client socket submits its message to my server socket, and the message from the second client socket is not arriving at the server socket. That means, that for the first client socket the while loop is interrupted after a succesful message, and the second client ends in an infinite while loop. If I test each client socket seperately in a test class, each client socket is submitting its message correctly to my server socket. By watching TCPView I noticed, that the client socket does not respond, as long as my port is used.
I read, that the second client socket should still respond its message, even if the port was used. In my case, the second client socket should always respond about a second after the first one. But I can't get them to work one after another.
So, here is my code for the method, which is waiting for client messages:
public void listenToSocket()
{
serverSocket = null;
thread = null;
SocketAddress adress = new InetSocketAddress(CommunicationValues.SOCKET_PORT);
try {
serverSocket = new ServerSocket();
serverSocket.setReuseAddress(true);
serverSocket.bind(adress);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
System.exit(0);
}
while(true){
try
{
Socket clientSocket = serverSocket.accept();
thread = new SocketMessageThread(clientSocket);
thread.start();
} catch (IOException e) {
System.out.println("MyServerSocket caught an error: \n" + e.getMessage());
e.printStackTrace();
}
}
}
This method is called in a thread. The structure looks like this:
SocketListenerThread calls the method listenToSocket() from class SocketListener
listenToSocket() is described above
The SocketMessageThread is handling the message output of the client socket in its run()-method.
EDIT
Here is the code of my SocketMessageThread:
public class SocketMessageThread extends Thread{
private Socket clientSocket;
private static int nameCounter = 0;
public SocketMessageThread(Socket clientSocket) {
this.clientSocket = clientSocket;
this.setDaemon(true);
this.setName("SocketMessageThread" + (nameCounter++));
}
public void run() {
try (
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));)
{
while (in.ready())
{
String inLine = in.readLine();
CommunicationValues.MESSAGE_MEMORIZER = inLine;
}
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}}
EDIT 2
Both clients only communicate with one particular message. E.g. when a client is started up, it mentioned, that the startup was successful with a single message. There are no repeating messages coming from the client sockets until the server sockets catches them. So if the server socket doesn't catch that one message, it's gone, and it won't be sent again by the client socket.
while (in.ready())
{
// ...
}
Classic misuse of ready(). Exchange all this for:
String inLine;
while ((inLine = in.readLine()) != null)
{
CommunicationValues.MESSAGE_MEMORIZER = inLine;
}
Presumably there is more code that you haven't shown us: otherwise all this will do is memorize the last line sent.

Interrupt server thread when client closes TCP connection

I have a multithreaded TCP Server in Java which allows connections from several clients and starts a new ServerThread for each connected Client:
Server Class:
while (!Thread.currentThread().isInterrupted()) {
try {
// Create a new thread for each incoming connection.
Socket clientSocket = serverSocket.accept();
ServerThread serverThread = new ServerThread(clientSocket, this);
serverThread.run();
} catch (IOException e) {
e.printStackTrace();
}
}
After a specific timeout, a client closes its socket. How can I interrupt the ServerThread which was connected with the client?
clientsocket.isClosed() and !clientSocket.isConnected() don't work for some reason.
Finally, I got it working with the following snippets (the solution is the socket in the resource block and the endless in.readLine() == null):
Server class
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
// Create a new thread for each incoming connection.
Socket clientSocket = serverSocket.accept();
ServerThread serverThread = new ServerThread(clientSocket, this);
serverThread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
ServerThread class:
public void run() {
try (Socket socket = clientSocket; // Enable auto-close for socket...
PrintWriter out = ...; BufferedReader in = ...;) {
...
while (!clientSocket.isClosed() && !isInterrupted()) {
if (in.readLine() == null) {
break;
}
}
System.err.println("Client with port " + clientSocket.getPort() + " closed connection to server.");
} catch (IOException e) {
e.printStackTrace();
}
}
Client class: I use the same try with resource block as in the ServerThread class
If the client closes a TCP socket uncleanly without sending an explicit FIN (for example, if the client crashes) then the server will not know about it until it next tries to send a packet to the client (at which point the client will sent an RST packet to tell the server the socket was closed).
Assuming you have control of both client and server code, the most robust way to check the connection is to implement a heartbeat mechanism between the two so they are regularly pinging a small piece of data between them to check the validity of the connection.
Keep alive socket option is the standard way to watch persistent TCP connection.
If your server was in the blocking read operation during the abort you'll get java.io.IOException: read failed. In the asynchronous case you'll receive read key with -1.
In the write state you'll get: Connection reset by peer: socket write error.
Just handle the exceptions or error codes to shutdown the thread if connection is not recoverable.

java.net.SocketException: Socket is closed

When a user connects to my server, I'm accepting the connection, storing the connected clients details in an arraylist then im trying to send that list to the client to create an asynchronous list. However, when I try to send the list it breaks the connection and causes the error;
java.net.SocketException: Socket is closed
My server class;
while (true) {
Socket clientSocket = serverSocket.accept();
ServerClientComs clientThread = new ServerClientComs(clientSocket);
getUsername(clientSocket, clientThread);
updateList();
try {
clientThread.sendList(connections);
clientThread.initialiseCommunication();
clientThread.start();
}
catch (IOException error) {
System.out.println("Server: Unable to initialise client thread! - " + error);
}
}
ServerClientComs Class;
public ServerClientComs(Socket clientSocket) {
super();
this.client = client;
this.clientSocket = clientSocket;
}
public void initialiseCommunication() throws IOException {
output = new PrintWriter(this.clientSocket.getOutputStream(), true);
input = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
}
public void sendList(ArrayList connections) throws IOException
{
oos = new ObjectOutputStream(this.clientSocket.getOutputStream());
oos.writeObject(connections);
oos.close();
}
Been playing about with this for a good hour, getting annoying now. any help is greatly appreciated!
A 'Socket closed' exception means that the application that caught the exception closed the socket and then kept trying to use it. Please note that closing the input or output stream of a socket closes the other stream and the socket as well. According to your statements seems you close the stream before using the socket to send data.

Can a process connect to a socket that itself created?

EDIT: The code below throws no exception but has no output and hangs. It should output "Test message". In main(), we start a thread that's given a server socket listening on a random port. The main thread the tries to connect and communicate with the ServerSocket on that same random port, but is apparently failing. Why?
public class IntraProcSockTest {
private static int port;
private class Listener extends Thread {
public Listener() {
}
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(0);
port = serverSocket.getLocalPort();
Socket socket = serverSocket.accept();
BufferedReader in;
String fromClient;
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
while ((fromClient = in.readLine()) != null) {
System.out.println("From client: " + fromClient);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public IntraProcSockTest() {
new Listener().start();
}
public static void main(String[] args) {
new IntraProcSockTest();
try {
Thread.sleep(5000);
Socket socket = new Socket("localhost", port);
PrintWriter socketOut = new PrintWriter(socket.getOutputStream());
socketOut.println("Test message");
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
A process can connect to a socket created by itself, there is no problem. Show us the code that throws an exception and/or more details about the exception.
First of all, be careful not to specify a local port for the client socket (the one connecting to the other which is listening). Let the OS choose a random port. Remember that any socket is identified by four elements (remote host, local host, remote port, local port), if you bind both the server socket and the client socket on the same local port, let it be 4498, both sockets are defined as follows: (localhost, localhost, 4498, 4498) and this doesn't work. I suspect this might be your problem.
To avoid such problems, client sockets are often bound to a random port, chosen by the OS. Show us your code, expecially the part in which the client sockets gets created and connects to the server socket.
And about IPC, it is not always bad to use sockets as an inter-process or even intra-process communication technique. The performance is worse, obviously, and you might loose some code readability, but your software will be easily portable to a network (distributed) application. It's up to your plans, it's not like IPC sockets == bad.
To create a Socket connection in one thread you can.
ServerSocket ss = new ServerSocket(0); // open a random free port.
Socket c = new Socket(ss.getInetAddress(), ss.getLocalPort());
Socket s = ss.accept();
ss.close();
final byte[] bytes = "Hello World!".getBytes();
final OutputStream out = c.getOutputStream();
out.write(bytes.length);
out.write(bytes);
final DataInputStream in = new DataInputStream(s.getInputStream());
int len = in.read();
final byte[] b = new byte[len];
in.readFully(b);
System.out.println(new String(b));
c.close();
s.close();
If all you want is IPC within a Process, a socket is not the fastest or simplest way to go. Try using a Pipe (NIO) or PipeInput/OutputStream (IO). Its faster and simpler.
Pipe pipe = Pipe.open();
SinkChannel sink = pipe.sink();
SourceChannel source = pipe.source();
or
PipedOutputStream output = new PipedOutputStream();
PipedInputStream input = new PipedOutputStream(output);
BTW: You can connect a client and server Socket in the same thread, however
Using an Exchanger is 10x faster, and using a ring buffer is faster again.
If you want convenience, using an ExecutorService is the best way to deleagte work to a background pool of threads. This can still perform millions of tasks per second.

Categories

Resources