I am trying to keep a connection between the server and my java client alive. This is my code:
import io.socket.client.*;
import io.socket.client.IO;
import java.net.URISyntaxException;
public class Main {
public static void main(String[] args) throws URISyntaxException, InterruptedException {
IO.Options opts = new IO.Options();
opts.reconnection = true;
Socket socket = IO.socket("http://localhost:3000", opts);
socket.connect();
socket.on("disconnect", args123 -> System.out.println("disconnect"));
Thread t = new Thread(new test(socket));
t.start();
}
}
class test implements Runnable{
private Socket socket;
public test(Socket socket){
this.socket = socket;
}
#Override
public void run() {
try {
Thread.sleep(3000);
socket.emit("test","test");
System.out.println("test");
} catch (Exception e) {
e.printStackTrace();
}
}
}
The test event in the thread does not arrive on the server because my client disconnects automatically.
I also tried this option for my server:
{transports: ['websocket'], upgrade: false}
or setting the ping interval and timeout interval
I believe your server is a "http" server. So that, you can keep connection alive, but you have to tell this to the server. This is done by request headers. So, simply, I would send "Connection: keep-alive" header. Moreover, your code doesn't look like an http implementation. So, first you should start implementing "http" protocol, then send "Connection: keep-alive" header.
Trying to keep a connection alive from client is not enough to keep really it alive. You have to agree with server.
Check how you can keep alive a http connection on https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Keep-Alive
Related
Long story short, I stole and modified some code from GeeksForGeeks to practice with sockets. Running code modified for localhost works fine on desktop, but when modifying and attempting to host on Heroku, I can't seem get a connection between the server and client. Server appears to launch and run fine on Heroku, and logs connections that I'm not even making (no idea where those are coming from). Client on the other hand seems to connect, but then doesn't do anything when I send a message. Server doesn't even log my attempted connection, so I know it probably isn't even connecting.
Server code: https://github.com/RenegadeB5/socket in /src/main/java/
Client Code:
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class Client
{
public static void main(String args[]) throws UnknownHostException, IOException
{
Scanner scn = new Scanner(System.in);
// establish the connection
Socket s = new Socket("<my app name>.herokuapp.com", 80);
// obtaining input and out streams
DataInputStream dis = new DataInputStream(s.getInputStream());
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
// sendMessage thread
Thread sendMessage = new Thread(new Runnable()
{
#Override
public void run() {
while (true) {
// read the message to deliver.
String msg = scn.nextLine();
try {
// write on the output stream
dos.writeUTF(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
// readMessage thread
Thread readMessage = new Thread(new Runnable()
{
#Override
public void run() {
while (true) {
try {
// read the message sent to this client
String msg = dis.readUTF();
System.out.println(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
sendMessage.start();
readMessage.start();
}
}
I've tried so many different combinations and solutions, and can't find any examples of this being done before. I'd like to know what I'm doing wrong so that I can move on from this headache. Thanks in advance!
Java Socket and ServerSocket use TPC, which is not supported for free by Heroku. As a result, the server will run fine, but anything being sent via TCP, including connection attempts, will not make it to your server unless they are done via http.
public class Slave implements Runnable {
public ServerSocket slaveSocket;
public Slave(ServerSocket sk) {socket = sk;}
#Override
public void run() {
Socket client = slaveSocket.accept(); // slave will wait to serve a client
// more code...
Socket clientPart2 = slaveSocket.accept();
// more code...
}
}
public class Server {
public static void main(String[] args) {
// for example only, incomplete code
ServerSocket serverSocket = new ServerSocket(0); // a client connect to 8088
Slave slave = new Slave(serverSocket);
new Thread(slave).start(); // slave serve the current client, the server wait for new client
// send new slave's port to client ...
}
}
So I have a server that serves multiple clients at once. Whenever a client connects, the server will create a new Slave, send the IP/port of that slave to the client, then the client will work with the slave.
However, if the client receives the slave's address then do nothing (or quit) (Edit: it means the client and server are connected but the client do nothing, because for example the user goes for lunch) slaveSocket.accept() causes that slave Thread to run forever, which is wasteful.
I want the slave thread to exit after 30 second of waiting for slaveSocket.accept(). Since slaveSocket.accept() is blocking, I cannot do that from inside the void run().
What is the correct, clean way to solve this problem? Thank you.
Edit 1: a ServerSocket is passed to the slave because the client can have multiple processes that will connect to that slave. So it doesn't just perform one function.
If you set a timeout with setSoTimeout and no client connects, ServerSocket.accept will throw an exception. You can catch this exception.
To set a timeout of 30 seconds, use:
serverSocket.setSoTimeout(30000)
Non-blocking I/O:
Take a look at AsynchronousServerSocketChannel's accept method which returns a Future. Then the Future has a getter with timeout which can do what you are asking.
Note: you may read a related tutorial.
Then the getter will return an AsynchronousSocketChannel which can be converted back to blocking via the corresponding Channels.newInputStream and Channels.newOutputStream methods to be used with the blocking approach in the worker threads.
Blocking I/O:
I think you actually meant on how to implement a server which accepts clients sequentially and serves them in parallel, with blocking I/O. If that is the case, then you may take a look at the following example:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Objects;
public class Main {
public static class Worker implements Runnable {
private final Socket sck;
private OutputStream os;
private InputStream is;
public Worker(final Socket sck) {
this.sck = Objects.requireNonNull(sck);
}
#Override
public void run() {
try {
os = sck.getOutputStream();
is = sck.getInputStream();
//ALL the work with the client goes here, unless you need more than one connections with him.
}
catch (final IOException iox) {
System.err.println(iox);
}
finally {
try { is.close(); } catch (final IOException | RuntimeException x) {}
try { os.close(); } catch (final IOException | RuntimeException x) {}
try { sck.close(); } catch (final IOException | RuntimeException x) {}
}
}
}
public static void main(final String[] args) {
ServerSocket srv = null;
try {
srv = new ServerSocket(8088);
while (true)
new Thread(new Worker(srv.accept())).start();
}
catch (final IOException iox) {
System.err.println(iox);
}
finally {
try { srv.close(); } catch (final IOException | RuntimeException x) {}
}
}
}
There are two readers plugged to the internal network. They just send data to the server machine, where I want to have this java app running receiving the data. It won't be that much data. Each reader could be transmitting single strings like "1234567" to a rate as much as maybe half a dozen times per second.
Without entering into much detail about the readers, they are datalogic and both are different models, but with this in common: They are configured to transmit the data via tcp/ip to a certain ip:port.
I tested the data trasmission with this software: https://www.hw-group.com//products/hercules/index_en.html to see if I'm receiving the data properly and it does check out, it works well.
The problem comes when I run my TCP server implementation: I receive the data from one of the devices 100% of the times, while the other one is hit and miss: Sometimes the data sent over the network never makes it to my app and I don't know why.
I'm pasting the code of what I'm using: It's simple but, with my java knowledge and after digging around the internet, it's the best I came up with.
Here's the java file with the main:
package tcpserverclasstest;
public class TCPServerClassTest {
public static void main(String[] args) throws InterruptedException {
TCPServerThread myTCPServerThread = new TCPServerThread();
myTCPServerThread.start();
}
}
Here's TCPServer.java:
package tcpserverclasstest;
import java.io.IOException;
import java.net.Socket;
import java.io.*;
public class TCPServer extends Thread {
public static final int PORT_NUMBER = 4413;
protected Socket socket;
public TCPServer(Socket socket) {
this.socket = socket;
System.out.println("New client connected from " + socket.getInetAddress().getHostAddress());
start();
}
public void run() {
InputStream in = null;
try {
in = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String request;
request = br.readLine();
System.out.println("Message received:" + request);
} catch (IOException ex) {
System.out.println("Unable to get streams from client");
} finally {
try {
in.close();
socket.close();
System.out.println("Socket closed");
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
And here's TCPServerThread.java:
package tcpserverclasstest;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServerThread extends Thread {
public static final int PORT_NUMBER = 4413;
protected Socket socket;
public void run(){
System.out.println("Waiting for incoming connections on port " + PORT_NUMBER);
ServerSocket server = null;
try {
server = new ServerSocket(PORT_NUMBER);
server.setReceiveBufferSize(262144);
server.setReuseAddress(true);
while (true) {
new TCPServer(server.accept());
}
} catch (IOException ex) {
System.out.println("Unable to start server.");
} finally {
try {
if (server != null)
server.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
I tried to implement the server on a thread since I want to implement this into a bigger project in the future and I don't want that app locked in the loop that is waiting for connections.
Any clues on what should I do to see why I'm not receiving some of the data? Any suggestion on a better way to achieve this?
Thanks!
first thing that comes to mind is your server only connects to one of the clients. Your TCPServerThread's run method listens for one connection and when it is made it initializes a TCPServer with this connection, meaning only one of the readers connects. Maybe after connecting to one reader you can listen for other.
Second, your TCPServer reads only one line and then closes the connection, and a line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r'), or a carriage return followed immediately by a linefeed. So your readers should send linefeed ('\n', or '\r', or '\r\n'). If not you shouldn't use readLine, maybe read some amount of data in a while loop.
To debug your TCP connections and really be sure the data is actually coming to your server, you can use WireShark. This shows all the packets coming in your network card and you can filter based on tcp.port to see only your connections.
I am trying to open multiple ports on a server socket so that i could connect multiple clients. Each time i create a create a thread and start it (i know the overridden run method will be invoked) i open a port and listen for a client .
But the problem is that when i run the client socket project and try to connect to the port i opened in server ,it says java.net.connectException : connection refused:connect.
I also noticed a peculiar thing happenning.The output in the console window is different every time i run the "server code "
i have been working on this for the last 3 days and i have achieved nothing i guess.
note: this problem is unique for me as i have not found this particular problem on this forum any where so please be kind as i am a newbie to java and socket programming though i have been coding on c++ for quite some time now .
server socket
import java.io.*;
import java.net.*;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.*;
public class TryThreads extends Thread
{
private int Portnumber;
private static String inputLine;
public TryThreads(int portNumber)
{
Portnumber = portNumber;
setDaemon(true);
}
public static void main(String[] args)
{
//create three threads
Thread first = new TryThreads(63400);
Thread second = new TryThreads(63401);
first.start();
second.start();
//third.start();
System.out.println("ending main");
return;
}
public void run()
{
try
{
System.out.println("one socket port opened");
ServerSocket serverSocket = new ServerSocket(Portnumber);
System.out.println("one socket port opened");
while (true)
{
System.out.println("ending main2");
//System.out.println("one socket port opened");
Socket clientSocket = serverSocket.accept();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
while((inputLine = bufferedReader.readLine()) != null)
System.out.println(inputLine);
}
}
catch(IOException e)
{
System.out.println(e);
}
}
}
client socket
import java.io.*;
import java.net.Socket;
public class client
{
private static PrintWriter printWriter;
public static void main(String[] args)
{
BufferedReader in = null;
try
{
Socket socket = new Socket("localhost",63400);
printWriter = new PrintWriter(socket.getOutputStream(),true);
printWriter.println("Hello Socket");
printWriter.println("EYYYYYAAAAAAAA!!!!");
}
catch(Exception e)
{
System.out.println(e);
}
}
}
In your TryThreads constructor, use:
setDaemon(false);
You have set your server threads to be daemon threads and they are therefore terminating as soon as main exits, so your server is stopping as soon as you start it.
See Thread.setDaemon():
The Java Virtual Machine exits when the only threads running are all daemon threads.
By the way, after the above issue is corrected, be aware that your implementation will lead to the server receiving a "connection reset" SocketException, which will break your server thread out of its loop and prevent it from accepting additional exceptions. You can fix this on the client side by doing socket.close() before you exit to ensure a graceful shutdown, but you will still want to fix it on the server side since you cannot assume that clients will be well-behaved.
Normally whenever you want to write a message using PrintWriter, you need to flush it when your done (printwriter.flush()). That makes sure the message is sent.
Using the default socket implementation on Windows, I was not able to find any effective method to stop Socket.connect(). This answer suggests Thread.interrupt() will not work, but Socket.close() will. However, in my trial, the latter didn't work either.
My goal is to terminate the application quickly and cleanly (i.e. clean up work needs to be done after the socket termination). I do not want to use the timeout in Socket.connect() because the process can be killed before a reasonable timeout has expired.
import java.net.InetSocketAddress;
import java.net.Socket;
public class ComTest {
static Socket s;
static Thread t;
public static void main(String[] args) throws Exception {
s = new Socket();
InetSocketAddress addr = new InetSocketAddress("10.1.1.1", 11);
p(addr);
t = Thread.currentThread();
(new Thread() {
#Override
public void run() {
try {
sleep(4000);
p("Closing...");
s.close();
p("Closed");
t.interrupt();
p("Interrupted");
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
s.connect(addr);
}
static void p(Object o) {
System.out.println(o);
}
}
Output:
/10.1.1.1:11
Closing...
Closed
Interrupted
(A few seconds later)
Exception in thread "main" java.net.SocketException: Socket operation on nonsocket: connect
You fork the thread and then the main thread is trying to make the connection to the remote server. The socket is not yet connected so I suspect s.close() does nothing on a socket that is not connected. It's hard to see what the INET socket implementation does here. t.interrupt(); won't work because the connect(...) is not interruptible.
You could use the NIO SocketChannel.connect(...) which looks to be interruptible. Maybe something like:
SocketChannel sc = SocketChannel.open();
// this can be interrupted
boolean connected = sc.connect(t.address);
Not sure if that would help though.