Java - ServerSocket accept() method repeating in while(true) loop - java

Hopefully someone can shed some light on this one, and provide a workaround, or illuminate some method I'm missing here.
Just messing around trying to create a really simple web server.
So far I have:
public class SocketTest {
public static void main(String[] args) throws IOException {
ServerSocket sock = new ServerSocket(9876);
while(true) {
System.out.println("Before");
Socket conn = sock.accept();
System.out.println("After");
conn.close();
}
}
}
Then, once the project is running, the output window displays:
Before
Which is what I expect, but then as soon as I type:
127.0.0.1:9876
Into a web browser, I end up with:
Before
After
Before
After
Before
After
Before
Showing. So the browser is obviously connecting to that port multiple times, but only the first connection contains any info in its page header.
While writing this, I've decided to go a little further with my experimentation's, and come up with:
public class SocketTest {
public static void main(String[] args) throws IOException {
ServerSocket sock = new ServerSocket(9876);
while(true) {
System.out.println("Before");
Socket conn = sock.accept();
System.out.println("After");
Scanner sc = new Scanner(conn.getInputStream());
System.out.println("BEFORE if...");
if (sc.hasNext()) {
System.out.println("INSIDE if...");
String[] cnr = sc.nextLine().split("\\s+");
System.out.println("Command: " + cnr[0] + " - URL: " + cnr[1]);
} else {
System.out.println("INSIDE ELSE!");
}
System.out.println("Closing...");
conn.close();
System.out.println("Closed!");
}
}
}
If you compile and run this code, you'll notice that upon first opening a page on the socket, you get the repeated socket opening, but it also appears to hang for about 10 seconds at the line:
if (sc.hasNext()) {
As though it's watching the InputStream() for a set period of time, to see if it contains any information or not..?
Also, if I send two actual pages in quick succession (or just refresh the page), it goes through immediately.
Can anyone shed some light on this?
Either how I can remove the waiting on an InputStream() that's never going to materialise, or how I can get it to ignore the phantom sockets.
Even a bit of background as to what's causing the anomaly would be great!

The accepting thread should never wait on socket's input, it should delegate data exchange to a separate thread and immediately return to execution of ServerSocket.accept() like it is described at the end of this example. For highly loaded servers (thousands of simultaneous connections), that threads can consume too much memory, so asynchronous IO can be used.

Related

Permanent and persistent Socket connection in java

I've created a client-server connection, something like a chat system. Previously I was using a while loop on the client side, and it was waiting to read a message from the console every time (of course server has a while loop as well to serve forever). But now, I'm trying to first create a connection at the beginning of the session, and then occasionally send a message during the session, so to maintain a permanent and persistent connection.
Currently, without the while loop, the client closes the connection and I don't know how to find a workaround.
Here is the client code:
import java.net.*;
import java.io.*;
public class ControlClientTest {
private Socket socket = null;
// private BufferedReader console = null;
private DataOutputStream streamOut = null;
public static void main(String args[]) throws InterruptedException {
ControlClientTest client = null;
String IP="127.0.0.1";
client = new ControlClientTest(IP, 5555);
}
public ControlClientTest(String serverName, int serverPort) throws InterruptedException {
System.out.println("Establishing connection. Please wait ...");
try {
socket = new Socket(serverName, serverPort);
System.out.println("Connected: " + socket);
start();
} catch (UnknownHostException uhe) {
System.out.println("Host unknown: " + uhe.getMessage());
} catch (IOException ioe) {
System.out.println("Unexpected exception: " + ioe.getMessage());
}
String line = "";
// while (!line.equals(".bye")) {
try {
Thread.sleep(1000);
//TODO get data from input
// line = console.readLine();
line="1";
if(line.equals("1"))
line="1,123";
streamOut.writeUTF(line);
streamOut.flush();
} catch (IOException ioe) {
System.out.println("Sending error: " + ioe.getMessage());
}
// }
}
public void start() throws IOException {
// console = new BufferedReader(new InputStreamReader(System.in));
streamOut = new DataOutputStream(socket.getOutputStream());
}
}
And here is the Server code:
import java.awt.*;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class ControlServer {
private Socket socket = null;
private ServerSocket server = null;
private DataInputStream streamIn = null;
public static void main(String args[]) {
ControlServer server = null;
server = new ControlServer(5555);
}
public ControlServer(int port) {
try {
System.out
.println("Binding to port " + port + ", please wait ...");
server = new ServerSocket(port);
System.out.println("Server started: " + server);
System.out.println("Waiting for a client ...");
socket = server.accept();
System.out.println("Client accepted: " + socket);
open();
boolean done = false;
while (!done) {
try {
String line = streamIn.readUTF();
// TODO get the data and do something
System.out.println(line);
done = line.equals(".bye");
} catch (IOException ioe) {
done = true;
}
}
close();
} catch (IOException ioe) {
System.out.println(ioe);
}
}
public void open() throws IOException {
streamIn = new DataInputStream(new BufferedInputStream(
socket.getInputStream()));
}
public void close() throws IOException {
if (socket != null)
socket.close();
if (streamIn != null)
streamIn.close();
}
}
I would like to summarize some good practices regarding the stability of TCP/IP connections which I apply on a daily basis.
Good practice 1 : Built-in Keep-Alive
socket.setKeepAlive(true);
It automatically sends a signal after a period of inactivity and checks for a reply. The keep-alive interval is operating system dependent though, and has some shortcomings. But all by all, it could improve the stability of your connection.
Good practice 2 : SoTimeout
Whenver you perform a read (or readUTF in your case), your thread will actually block forever. In my experience this is bad practice for the following reasons: It's difficult to close your application. Just calling socket.close() is dirty.
A clean solution, is a simple read time-out (e.g. 200ms). You can do this with the setSoTimeoutmethod. When the read() method timeouts it will throw a SocketTimeoutException. (which is a subclass of IOException).
socket.setSoTimeout(timeoutInterval);
Here is an example to implement the loop. Please note the shutdown condition. Just set it to true, and your thread will die peacefully.
while (!shutdown)
{
try
{
// some method that calls your read and parses the message.
code = readData();
if (code == null) continue;
}
catch (SocketTimeoutException ste)
{
// A SocketTimeoutExc. is a simple read timeout, just ignore it.
// other IOExceptions will not be stopped here.
}
}
Good practice 3 : Tcp No-Delay
Use the following setting when you are often interfacing small commands that need to be handled quickly.
try
{
socket.setTcpNoDelay(true);
}
catch (SocketException e)
{
}
Good practice 4 : A heartbeat
Actually there are a lot of side scenario's that are not covered yet.
One of them for example are server applications that are designed to only communicate with 1 client at a time. Sometimes they accept connections and even accept messages, but never reply to them.
Another one: sometimes when you lose your connection it actually can take a long time before your OS notices this. Possibly due to the shortcomings described in good practice 3, but also in more complex network situations (e.g. using RS232-To-Ethernet converters, VMware servers, etc) this happens often.
The solution here is to create a thread that sends a message every x seconds and then waits for a reply. (e.g. every 15 seconds). For this you need to create a second thread that just sends a message every 15 seconds. Secondly, you need to expand the code of good practice 2 a little bit.
try
{
code = readData();
if (code == null) continue;
lastRead = System.currentTimeMillis();
// whenever you receive the heart beat reply, just ignore it.
if (MSG_HEARTBEAT.equals(code)) continue;
// todo: handle other messages
}
catch (SocketTimeoutException ste)
{
// in a typical situation the soTimeout is about 200ms
// the heartbeat interval is usually a couple of seconds.
// and the heartbeat timeout interval a couple of seconds more.
if ((heartbeatTimeoutInterval > 0) &&
((System.currentTimeMillis() - lastRead) > heartbeatTimeoutInterval))
{
// no reply to heartbeat received.
// end the loop and perform a reconnect.
break;
}
}
You need to decide if your client or server should send the message. That decision is not so important. But e.g. if your client sends the message, then your client will need an additional thread to send the message. Your server should send a reply when it receives the message. When your client receives the answer, it should just continue (i.e. see code above). And both parties should check: "how long has it been?" in a very similar way.
You could wrap a thread around the connection and have it periodically send a status to keep the line open, say every 30 seconds or whatever. Then, when it actually has data to send it would reset the keep alive to be 30 seconds after the last transmission. The status could be helpful to see if the client is still alive anyway, so at least it can be a useful ping.
Also, you should change your server code, you appear to only handle one connection at the moment. You should loop and when a socket connection comes in spawn a thread to handle the client request and go back to listening. I may be reading to much into what may just be your test code, though.
Make the client socket connection wrapped around a thread. Use a blocking queue to wait for messages. There should only be a single sender queue throughout your application, so use a singleton pattern.
e.g.
QueueSingleton queue = QueueSingleton.getSenderQueue();
Message message = queue.take() // blocks thread
send(message); //send message to server
When you need to send a message to the server, you can use the blocking queue to send the message.
QueueSingleton queue = QueueSingleton.getSenderQueue();
queue.put(message)
The client thread will wake up and process the message.
For maintaining the connection, use a timer task. This is special type of thread that calls a run method repetitively at specified periods. You can use this to post a message, a ping message, every so often.
For processing the received message, you could have another thread, waiting for messages on another blocking queue (receiver queue). The client thread will put the received message on this queue.

Connection between jmonkey and netbeans

I'm working on a project for school. We are are making a harbour where you can load and unload ships. The control part is made in Netbeans and the simulation in JME.
We send data from Netbeans to JME via a socket. JME is running a serversocket who is liseting to the input from Netbeans.
For example Netbeans sends an ID of a container and the crane in JME gets that container and puts it on the shore so a verhicle can pick it up.
We change a count in the main (Main.count = 2) so the SimpleUpdate can call a method. The problem is that sometimes stuff is getting skipped. Also I think it's getting worse when we send more information for instance a vehicle that's getting the container. How can I fix this? And are there other ways to get a good connection?
The code:
Netbeans
Send client
public static void run() throws Exception
{
Socket socket = new Socket("Localhost", 4321);
out = new ObjectOutputStream(socket.getOutputStream());
}
//Sent arraystring to Simulation
public void sent(String sentString){
try {
out.writeObject(sentString);
} catch (IOException ex) {
Logger.getLogger(CommunicationWithSimulatoin.class.getName()).log(Level.SEVERE, null, ex);
}
}
Main send some stuff example
for(int i = Calculator.getContainersFromMaritime(); i > 1; i--)
{
Thread.sleep(50);
sim.sent("craneCon;" + i + ";");
System.out.println(i);
}
JME
Listener
public static void Listener() throws Exception {
boolean isRunning = true;
//Creates the server socket
ServerSocket sSocket = new ServerSocket(4321);
//Acception a connection from the client
Socket socket = sSocket.accept();
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
//Get the input from the client
while (isRunning) {
//Reads and prints the input
test = (String) in.readObject();
System.out.println(test);
String[] parts = receivedString.split(";");
if(parts[0].equals("ContainerPositionsMaritime"))
{
Maritime.ContainersOnBoard = receivedString.split(";");
Main.count = 0;
}
if(parts[0].equals("craneCon"))
{
int containerId = Integer.parseInt(parts[1]);
SeagoingCranes.idContainer = containerId;
Main.count = 2;
}
}
}
Main simpleupdate
public void simpleUpdate(float tpf) {
if(count == 0)
{
InitContainers();
//martime.setLocalTranslation(0, 500.0f, 0);
count = 999;
}
if(count == 2)
{
InitCrane(SeagoingCranes.idContainer);
count = 999;
}
if(martime != null)
{
martime.move(0,0,0.25f*tpf);
}
}
There are a number of problems with your program.
Firstly - you have potential race and thread contention issues as you have "count" which I assume is an integer value inside the SimpleApplication is being modified from one thread and read from another. Unless the value is declared as volatile this can cause all sorts of unexpected problems and odd behaviour and even declaring it as volatile is not recommended.
Your main issue though (even leaving aside the subtle problems) is being caused by the fact that in simpleUpdate() you are scanning count and then taking an action based on count. simpleUpdate() is called once for each frame as your jME3 application is running.
If you receive more than one message in a frame then only the last one will be acted on as the count will be modified again before the next simpleUpdate() runs.
The best way to do this is to use app.enqueue().
if(parts[0].equals("ContainerPositionsMaritime"))
{
final ContainersOnBoard containers = receivedString.split(";");
mainApp.enqueue(new Callable<Spatial>() {
public Spatial call() throws Exception {
mainApp.InitContainers(containers);
return null;
}
});
}
}
You can remove all the existing code from your simpleUpdate().
The Callable you enqueue will be called back from the JME3 thread in the next update and process the addition of the containers. By doing a similar thing for every different commands it will enqueue and process all the commands as the time comes. You can enqueue as many commands as you like and they will all be processed.
In general you should read up on AppStates, Controls and the threading model as they will allow you to make your code much more structured and organised.
http://hub.jmonkeyengine.org/wiki/doku.php/jme3:advanced:multithreading
http://hub.jmonkeyengine.org/wiki/doku.php/jme3:advanced:application_states
http://hub.jmonkeyengine.org/wiki/doku.php/jme3:advanced:custom_controls
P.S. You should try and follow Java style/coding conventions - for example methods should begin with lowercase. initContainers not InitContainers.

How to create a simultaneous connection between a server and a client on the same network in Java?

I am trying to create a MapleStory type game for my computer science final. It's basically a 2D RPG played over LAN. My question is how would I get the connection between two computers to be simultaneous?
class MagicServer extends Thread
{
private ServerSocket serverSocket;
public MagicServer(int port) throws IOException
{
serverSocket = new ServerSocket(port);
//serverSocket.setSoTimeout(10000);
}
public void run()
{
Scanner kb = new Scanner(System.in);
while(true)
{
try
{
System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "...");
Socket server = serverSocket.accept();
System.out.println("Just connected to " + server.getRemoteSocketAddress());
DataInputStream in = new DataInputStream(server.getInputStream());
DataOutputStream out = new DataOutputStream(server.getOutputStream());
System.out.println(in.readUTF());
for(int i=0; i<5; i++)
{
System.out.println(in.readUTF());
out.writeUTF(kb.nextLine());
}
server.close();
}
catch(SocketTimeoutException s)
{
System.out.println("Socket timed out!");
break;
}
catch(IOException e)
{
e.printStackTrace();
break;
}
}
}
public static void main(String [] args)
{
int port = 2001;
try
{
Thread t = new MagicServer(port);
t.start();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
I was experimenting with this and I can only send/recieve messages between two computers in order (i.e. server sends to client then client sends to server) and I cannot go out of order. How would I do this?
You have to de-couple your reads/writes by using multiple threads or through interlocked queues to manage your work.
In you loop, you force the serialization by doing a read then a write in the code.
There's no reason you couldn't spawn a reader thread that feeds into a queue to perform work by worker threads and writes happen on another thread. You just need to have synchronization on the work queues.
You can also poll the socket to see if there's any data available to read and if not, send any data waiting to be written.
There's more exotic ways to do it, and plenty of examples, search around and see what your comfortable with.
There's a similar thread here
You could use multiple threads to have a connection one way in one thread on one port and a connection the other way on a different port in the other thread. This could introduce some synchronization issues though, so I would recommend rethinking your design so that communication only needs to occur in one direction at a time (you can switch back and forth as often as you like if need be).

java I/O blocks thread on server side

i m working on client socket connection. client is a GPRS hardware device. i m receiving request from this client on my serversocket and then opening multiple threads. my problem is that when device/client close the socket then my IO detects that throws an exception but when i put off the battery from the device while sending the request to the serversocket it is blocked without throwing any exception. somebody suggested me to use setSOTimeout() to comeout from the blocking thread.
i have tried Socket.setSOTimeout(int) . but this is not working out in my case. i m sending my code properly.
// inside main class---
public class ServerSocketClass{
public ServerSocketClass() {
try{
serverSocket = new ServerSocket(port);//creating a serversokcet on a port
System.out.println("Server waiting for client on port " +
serverSocket.getLocalPort());
} catch (Exception e) {
e.printStackTrace();
handleExceptions("errorServerSocketOpen.txt", e);
System.exit(0);
}
try {
while (true) {
Socket clientSocket = serverSocket.accept();//accepting the client connection and //creating client socket
new AcceptConnection(clientSocket);//calling the constructor of other //class to open a new thread
System.out.println("constructor called.....");
}
} catch (Exception e) {
handleExceptions("errorClientSocketOpen.txt", e);
}
}
}
//inside other class---
public class AcceptConnection implements Runnable {
public AcceptConnection(Socket socket) {
this.clientSocket = socket;
if (clientSocket != null) {
new Thread(this).start();
}
public void run() {
// clientSocket.setSoTimeout(60000);// this is what i added.timeout on each client socket opened in threads
InputStream inputStream = clientSocket.getInputStream();
DataOutputStream dataOutputStream = new DataOutputStream(clientSocket.getOutputStream());
byte[] mainBuffer = new byte[2048];
int len = -1, totalLength = 0;
debugInfo = " GOING TO READ FROM SOCKET.... " + "\n";
while ((len = inputStream.read(mainBuffer)) > -1) {
totalLength = len;
}//end of while
} }//end of other class
now my problem is that when multiple threads are opened and i send the data from client than after 60 seconds it closes the main socket and stops receiving the data.and a readtimeout error occurs.
please help me out and tell me how my objective could be fulfilled.
thanks in advance
**
#stephen
**
ok stephen got it what u r trying to say... u r right on your statement "Well yes ... that's what you told it to do."May be i m not able to make u understand my problem or i m not getting the setSoTimeout() logic as i m newbie in java.
i would like to ask one more time...
this is how i m creating a new client socket for each client connection and opening a new thread for each client connection.
while (true) {
Socket clientSocket = serverSocket.accept();//accepting the client connection and //creating client socket
new AcceptConnection(clientSocket);//calling the constructor of other class to open a new thread
System.out.println("constructor called.....");
}
public void run() {
// clientSocket.setSoTimeout(60000);// this is what i added.timeout on each uclient socket opened in threads
........................................
.......................................
}
now i want to say if i m opening a new thread for a new client connection and i m separately putting setSoTimeout() on each client connection object then if a particular thread A is blocked on I/O while reading then after a timeout set in setSoTimeout(50000) ,say 50 sec ,only thread A should come out of read and give the exception, not other threads running simultaneously say B,C,D.but in my case after a timeout all threads returns after giving exception and in fact any new client connection gives the same error and server application stops receiving any data on read.
i want only thread A should give exception and come out from read without affecting other client socket objects(or threads).
now i hope i have told u everything about my confusion and problem.
please help me out and thanks a lot.
now my problem is that when multiple threads are opened and i send the data from client than after 60 seconds it closes the main socket and stops receiving the data.and a readtimeout error occurs.
Well yes ... that's what you told it to do.
As I think I said in my answer to your previous question, you cannot distinguish between these cases:
The client has no data to send for a period.
The network is partitioned for a period.
The client has disappeared from the network.
Another option that you have is to call Socket.setKeepAlive() to enable TCP keepalives. This causes the a special "keepalive" handshake to be performed periodically to ensure that the TCP/IP connection is still alive. Unfortunately, it doesn't look like you can set the TCP/IP keepalive interval in Java.
EDIT
NIO won't help. When I said "cannot" above ... I meant that it is PHYSICALLY IMPOSSIBLE to do it. Here's an analogy to help you understand.
The only communication between Outer
WoopWoop and the rest of the world is
by letter. Once a week my friend in
Outer WoopWoop (who lives alone) posts
a letter to me to fill me in on the
gossip. Last week I didn't receive a
letter from my friend. How can I tell if:
my friend has died,
my friend had no gossip last week,
the Outer WoopWoop postal workers have been on strike, or
all of the above?
The correct answer is that I cannot tell.

How to close a thread in Java?

I'm very new to Java, and I'm trying to modify an example of a socket server to power a flash-based game. To allow flash to connect to the server, I need to serve up a policy file.
I've never coded a server application before, so I'm not too familiar with the things which need to happen.
Anyway, I have made it so that it outputs the file, but for some reason it does so 10 times.
I need to close the thread before it continues to do it again. Below is the code I have, with a comment where I need to close the thread.
import java.io.*;
import java.net.*;
import java.util.Random;
public class Main {
private static int port=4041, maxConnections=0;
// Listen for incoming connections and handle them
public static void main(String[] args) {
int i=0;
try{
ServerSocket listener = new ServerSocket(port);
Socket server;
while((i++ < maxConnections) || (maxConnections == 0)){
doComms connection;
server = listener.accept();
doComms conn_c= new doComms(server);
Thread t = new Thread(conn_c);
t.start();
}
} catch (IOException ioe) {
System.out.println("IOException on socket listen: " + ioe);
ioe.printStackTrace();
}
}
}
class doComms implements Runnable {
private Socket server;
private String line,input;
doComms(Socket server) {
this.server=server;
}
public void run () {
char EOF = (char)0x00;
input="";
try {
// Get input from the client
DataInputStream in = new DataInputStream (server.getInputStream());
PrintStream out = new PrintStream(server.getOutputStream());
while((line = in.readLine()) != null && !line.equals(".")) {
input=input + line;
if(line.trim().equals("h")){
out.println("h"+EOF);
}
else if(line.trim().equals("i")){
Random randomGenerator = new Random();
int randomInt = randomGenerator.nextInt(4);
out.println("b"+randomInt+EOF);
}
else if(line.trim().equals("c")){ System.out.println("Player collision.");}
else if (line.trim().equals("<policy-file-request/>")) {
out.println("<?xml version=\"1.0\"?>\n<!DOCTYPE cross-domain-policy SYSTEM \"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd\"><cross-domain-policy>\n<site-control permitted-cross-domain-policies=\"all\"/>\n<allow-access-from domain=\"*\"/>\n</cross-domain-policy>"+EOF);
System.out.println("Responded to policy request");
// I need to close the thread / disconnect the client here.
}
else System.out.println("Unknown command: "+line.trim());
}
server.close();
} catch (IOException ioe) {
System.out.println("IOException on socket listen: " + ioe);
ioe.printStackTrace();
}
}
}
Also, a small extra thing, in NetBeans, it underlines "import java.io.*;" and says incorrect package, but it still works fine.
Edit:
I've worked out that the reason it sends it 10 times is that it is receiving 10 lines in a single send operation. I have tried adding a "return;" under where it sends the policy XML, but it still doesn't seem to d/c the client. I should also note than I am intending for this to be a multiplayer server, so I need to keep the socket open and just close one thread.
At first glance, your run() method looks like it should terminate normally. I suspect your loop:
while((i++ < maxConnections) || (maxConnections == 0)){
Since maxConnections is initialized to 0 and is never incremented, the loop seems to run infinitely and create many threads - probably as many as the socket can accept listeners. And then it breaks out from the loop with an IOException. Is this what's actually happening?
Update: apparently not... out of ideas for now.
Your code makes sense. What is your input? If you have 10 lines saying "<policy-file-request/>" , then indeed it will print the file 10 times. What about all the other if clauses you have there? In each one you print something + EOF, but surely you just want to print one response per request. Also your 'input' variable is unused.
The thread will die after you return from doComms.run(). Please capitalize the start of class names in Java: it should be DoComms, just to make the code easier to follow for other Java programmers.
To close the connection, your call to server.close() should do it. To make sure the output is sent fully first, you should call close() or flush() on your PrintStream before you call Socket.close().
What input are you sending? It looks like if you only send <policy-file-request/> once from the client, you'll only get the file once.
Not sure about NetBeans, but is it complaining that you don't have a package specified at the top of your .java file? Try adding the following package declaration, with the path relative to the top of the NetBeans project:
package my.path.to.this.directory;
I'd suggest running both the server and the client in a debugger and stepping through the execution to see what happens at each point in time. This will help you confirm the expected values at every point. Eclipse and other Java IDEs have pretty good (and easy-to-use) debuggers.
As far as your code:
I would do line.trim() once for each
loop iteration, instead of
trim()'ing repeatedly and
unnecessarily creating extra
objects.
Make sure the client and server both flush() the Socket's OutputStream after each request/response. If the socket's OutputStream has not been flushed, the InputStream on the other end of the connection may block waiting for input, while the OutputStream blocks waiting to fill its buffer.
What does the code in the client
look like? Are you sure it's
sending a null or "." to close the
connection? Do you need to trim() before checking for a "."
As others have mentioned, your code does not follow typical Java coding conventions. I'd suggest getting up to speed by reading the published code conventions for Java.

Categories

Resources