Strange behaviour of ServerSocket.accept method - java

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?

Related

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.

Can two different socket instances listen to same TCP port ( Port already in use )

I have a TcpServer class that is responsible to, well, act like a tcp server. You can find the class below :
public class TcpServer {
private ServerSocket serverSocket;
private Socket socket;
private int locallyBoundPort;
public TcpServer() {
}
public TcpServer(int locallyBoundPort) {
try {
this.serverSocket = new ServerSocket(locallyBoundPort);
serverSocket.setReuseAddress(true);
} catch (IOException e) {
System.out.println("Error at binding to port TCP : " + locallyBoundPort + "...cause : " + e.getMessage());
}
socket = null;
}
public void accept() {
try {
socket = serverSocket.accept();
socket.setReuseAddress(true);
} catch (IOException e) {
System.out.println("Error at accept : " + locallyBoundPort);
}
}
public void send(Data data) throws IOException {
if(socket != null) {
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
out.writeObject(data);
}
}
public Data receive() throws ClassNotFoundException, IOException {
if(socket != null) {
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
return (Data) in.readObject();
} else {
return null;
}
}
public boolean bind(int port) throws IOException {
try {
this.serverSocket = new ServerSocket(port);
this.locallyBoundPort = port;
} catch(IOException e) {
return false;
}
return true;
}
public void close() {
try {
serverSocket.close();
socket.close();
} catch (IOException e) {
OzumUtils.print("IOException in close, TcpServer");
}
}
public int getLocallyBoundPort() {
return locallyBoundPort;
}
public Socket getSocket() {
return socket;
}
public ServerSocket getServerSocket() {
return serverSocket;
}
}
And I have a code piece that does this :
TcpServer tcpServer = new TcpServer(LocalPort);
while(1)
{
tcpServer.accept();
Thread thread = new Thread(new runnable(tcpServer));
thread.start();
tcpServer = new TcpServer(LocalPort);
}
However I am getting a port already in use error. I thought two different socket instances could listen to the same port as multiplexing allows two connections through the same port when the connector has different ip or port ?
What am I missing?
You cannot bind two tcp server sockets to the same port. reuseAddress is really for client sockets, and it does not work the way you think it does ... and the way you are using it would not do anything at all either way (because you are setting it after binding).
You don't really need to bind twice to the same port either. Just remove this line tcpServer = new TcpServer(LocalPort); from the bottom of your while loop, and you'll be all set.
The way this works is that you bind your server socket once and listen to the port. When a connection arrives, it forks a client socket for you to communicate with the client, and the original server socket continues to listen for more connections.
Basically, you need to remove the socket member (and any other state) from your TcpServer, and make the accept method return the accepted socket. Then make your runnable take that socket as a parameter instead of the TcpServer, and use that to serve the client connection. Then just keep calling accept in the loop, and forking threads for new connections same way you do know, except do not recreate the server every time.
Or, alternatively, remove the server socket and port from TcpServer, create the socket outside the loop, then while(true) call accept on it, create a new TcpServer with the returned client socket, and use it in a thread to process the connection.
Do not forget to close client sockets after you are done with them.
No, you can't use a port already in listening state. However any number of clients can connect to this same port. You don't need to listen to the port again, you just spawn a new thread to process the current connection and wait for a new one. For example, supposing you have a class TcpConnectionHanlder that implements Runnable and takes the Socket as parameter, the loop would look like
while (true) { //while(1) is not valid Java syntax
final Socket tcpSocket = tcpServer.accept(); // Get socket for incoming connection
final Thread thread = new Thread(new TcpConnectionHanlder(tcpSocket)); // Create a thread for this socket/client connection
thread.start(); // Launch the thread
// tcpServer = new TcpServer(LocalPort); <- not needed, port still listening.
}
Then in your TcpConnectionHanlder instance you handle this particular client (socket).

TCP client and server

I'm working on a project which expects a TCP client and Server, where server echoes the message back to client. Following is from the assignment:
The server application shall:
Listen for TCP connections on a well known IP address and port
Accept connections initiated on that port
Receive messages from the client and echo them back
Continue to do this until the client drops the connection.
The client application shall:
Establish a connection with the server at its well known IP address and port
Send messages in an asynchronous manner to the server. The format of the message is
of your choice; however, it must contain enough information in order for it to be
recognized on its return from the server.
I have completed the coding for Server, and this is what i've come up with for the client.
My questions:
What does it mean that Server listens for TCP connections on a well known IP and Port In my implementation, i've used ServerSocket which accepts the port server listens on. Did i interpret it correctly?
In my current implementation of TCPClient, client sends messages to Server, but the println() seems to be a blocking call, which makes it Synchronous. What can i do to make my client asynchronous?
For brevity, I havent added the code of TCPServer, let me know if it is needed
UPDATE**
Based on the feedback, i have modified by TCPClient class. After receiving client request, i spawn two threads ReceiveMessage and SendMessage. Doing that gives me following exception:
[Client] Message sent: Message from Client 97
[Client] Message sent: Message from Client 98
[Client] Message sent: Message from Client 99
[Client] Done Sending all the messages
java.net.SocketException: Socket closed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
at java.io.InputStreamReader.read(InputStreamReader.java:167)
at java.io.BufferedReader.fill(BufferedReader.java:136)
at java.io.BufferedReader.readLine(BufferedReader.java:299)
at java.io.BufferedReader.readLine(BufferedReader.java:362)
at org.chanders.client.ReceiveMessage.run(ReceiveMessage.java:18)
at java.lang.Thread.run(Thread.java:680)
Following is the new Client Code:
public class TCPClient {
Socket clientSocket = null;
OutputStream out = null;
BufferedReader in = null;
String message = "Hello from Client";
int messagecount = 100;
// server credentials
private static final String SERVER_ADDRESS = "localhost";
private static final int SERVER_PORT = 50001;
protected void execute() {
try {
clientSocket = new Socket(SERVER_ADDRESS, SERVER_PORT);
Thread send = new Thread(new SendMessage(clientSocket.getOutputStream()));
Thread receive = new Thread(new ReceiveMessage(clientSocket.getInputStream()));
send.start();
receive.start();
//For server to wait until send and receive threads finish
send.join();
receive.join();
} catch (UnknownHostException uhe) {
System.err.println("Couldnt find host: " + SERVER_ADDRESS);
uhe.printStackTrace();
System.exit(-1);
}catch(IOException ioe) {
System.err.println("Couldnt get I/O: " + SERVER_ADDRESS);
ioe.printStackTrace();
System.exit(-1);
}catch(InterruptedException ie) {
System.err.println("Thread.join failed: ");
ie.printStackTrace();
System.exit(-1);
}
finally {
//cleanup();
}
}
private void cleanup() {
try {
clientSocket.close();
}catch(Exception e) {
e.printStackTrace();
System.exit(-1);
}
}
public static void main(String[] args) {
TCPClient client = new TCPClient();
client.execute();
}
public class SendMessage implements Runnable {
OutputStream out = null;
String message = "Message from Client";
int messageCount = 100;
public SendMessage(OutputStream out) {
this.out = out;
}
public void run() {
PrintWriter writer = new PrintWriter(out);
try {
for (int i = 0; i < messageCount; i++) {
String m = message + " " + i;
writer.println(m);
System.out.println("[Client] Message sent: " + m);
}
System.out.println("[Client] Done Sending all the messages");
} catch (Exception e) {
e.printStackTrace();
System.exit(-1);
} finally {
cleanup();
}
}
private void cleanup() {
try {
out.close();
}catch(Exception e) {
e.printStackTrace();
System.exit(-1);
}
}
}
public class ReceiveMessage implements Runnable {
InputStream in = null;
String message;
public ReceiveMessage(InputStream in) {
this.in = in;
}
public void run() {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
try {
while ((message = reader.readLine()) != null) {
System.out.println("[Client] Received message from Server: "
+ message);
}
System.out.println("[Client] Done Receiving messages from Server");
} catch (Exception e) {
e.printStackTrace();
} finally {
cleanup();
}
}
private void cleanup() {
try {
in.close();
}catch(Exception e) {
e.printStackTrace();
System.exit(-1);
}
}
}
In this context, Asynchronous probably doesn't mean that you can't use println, but that the client must be able to recevie messages while it's sending new ones.
The client should create the socket and then create two threads, one to send messages and the other to recive and print them.
Update
To avoid the exception, use clientSocket.shutdownOutput() instead of closing the output stream.
You could move the send code back to the main thread and keep a separate thread for the receive code or call shutdownOutput() after joining the send thread. Whatever works better for you.
Use a separate thread for each client. When you write something, in the server end , there must be a method which accepts the string. Otherwise it will be blocking. Paste your server code.
Well known ports are port numbers that have been specifically designated for particular protocols, for example 80 is for HTTP and 443 is for HTTPS. Are you meant to be implementing a particular protocol? If you are I would suggest you use the port number for that protocol. Wikipedia has a list of well known port numbers here:
http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
If this is a professional assignment (as opposed to a some homework) then I would strongly recommend the Netty Server, which is basically a NIO client server framework. It significantly simplifies/streamlines the development of this sort.
Make sure to check their documentation as it provides examples implementing exactly the server/client functionality stated in the question.
If this is a homework then this example should provide all necessary details. Please also check Oracle resources.

set option for sockets in java

I have a server in Java which listens for incoming connection to a specific port. And everything works as expected, my clients connect to the server and I'm able to send data between them.
My problem is that, when I shut down my client, turn it on again and try to reconnect, it won't connect (my server stays on all the time).
For me to reconnect, I have to restart my server again.
So I tried doing this on my server side:
InetSocketAddress serverAddr = new InetSocketAddress(serverIpAddress, serverPort);
serverSocket = new ServerSocket();
serverSocket.setReuseAddress(true);
//I tries setting up a reuse option
serverSocket.bind(serverAddr);
Even after setReuseAddress() my client won't connect unless I restart my server!
Has anyone any idea of how could that be done?
EDIT2:
try {
while(true){
clientSocket = serverSocket.accept();
System.out.println("S-a conectat clientul de monitorizare!");
os=new ObjectOutputStream(clientSocket.getOutputStream());
try{
coord=(Coordinate)queue.take();
System.out.println(coord.getLat()+coord.getLon()+coord.getVit()+coord.getwId()+coord.getime());
os.writeObject(coord);
os.flush();
}
catch(Exception e)
{
e.printStackTrace();
}
}
} catch (IOException e) {
System.out.println(e);
try {
clientSocket.close();
os.close();
}catch(Exception e1) {
e1.printStackTrace();
}
}
New edit:
Thread pool server:
Main:
ThreadPooledServer server = new ThreadPooledServer(queue,7001);
new Thread(server).start();
ThreadPooledServer:
public class ThreadPooledServer implements Runnable {
protected ExecutorService threadPool =
Executors.newFixedThreadPool(5);
public void run() {
openServerSocket();
while (!isStopped()) {
Socket clientSocket = null;
try {
System.out.println("Serverul asteapta clienti spre conectare");
clientSocket = this.serverSocket.accept();
clientconnection++;
System.out.println("Serverul a acceptat clientul cu numarul:"
+ clientconnection);
} catch (IOException e) {
if (isStopped()) {
System.out.println("Server Stopped.");
return;
}
throw new RuntimeException("Error accepting client connection",
e);
}
WorkerRunnable workerRunnable = new WorkerRunnable(queue,clientSocket);
this.threadPool.execute(workerRunnable);
}
System.out.println("Server Stopped.");
}
public synchronized void stop() {
this.isStopped = true;
try {
this.threadPool.shutdown();
}
catch (IOException e) {
throw new RuntimeException("Error closing server", e);
}
}
private void openServerSocket() {
try {
InetSocketAddress serverAddr = new InetSocketAddress(SERVERIP,
serverPort);
serverSocket = new ServerSocket();
serverSocket.setReuseAddress(true);
serverSocket.bind(serverAddr);
} catch (IOException e) {
throw new RuntimeException("Cannot open port", e);
}
}
this.serverSocket.close();
In your run method you accept one client and then go in to an endless loop, trying to write data to the ObjectOutputStream. When the client closes the connection an exception is thrown because you can no longer write to the stream. At this point we're out of the endless loop(while(true) { .. }) and the run method ends.
If you want to keep accepting clients I suggest you move the while loop to the top of your code, above the accept to be exact.
Pseudo-ish code below(note: I'm not catching any exceptions etc.):
while (true)
{
// Wait for a client to connect..
Socket clientSocket = serverSocket.accept();
// Write to the client..
ObjectOutputStream os = new ObjectOutputStream(clientSocket.getOutputStream());
os.writeObject(coord);
os.flush();
}
Is your server single threaded for a purpose (do you only accept one client at a time) ? Usually, servers will spawn a separate thread for every connections, so it can listen more often for incoming connections, and so if the client's connection throws any errors, it won't affect the listening socket. At the moment, your server will listen to only one connection, and if an exception occurs handling the client's connection, simply move on and never listen again. In pseudocode, a typical server is like :
Server listening thread (main thread)
try {
create server socket and bind to port
while server is online
listen for incoming connections
if the client connection is accepted [1]
start client thread
catch exception
handle exception
finally
make sure the server socket is disconnected
cleanup
Server client connection thread
write to client socket to initialize connection
try
while scoket is opened
read data
data treatment
write response
catch exceptions
handle exception [2]
finally
close client socket
cleanup
[1] if your server handles only one client, it should refuse the connection, so the client doesn't wait for no reason
[2] if the exception is not about the socket, the client should be warned by a final write to the socket before closing it
Client thread (on the client's side)
try
connect to server
protocol handshake (optional) [4]
while socket is connected
client server communication
catch exception
handle excpetion
finally
close socket
[4] since the server should write to the socket first, the client should read from it for any welcome message or error messages before attempting to write anything.

Categories

Resources