This seems to be a popular problem, but I'm still having trouble finding a solution even after spending a lot of time troubleshooting. I'm hoping there's an updated solution.
I'm setting up a simple Server and Client with the KryoNet Java networking library. My problem is that my client disconnects immediately after connecting to the server.
Here is my code:
Server
public class TheServer extends Listener {
static Server server;
static final int PORT = 8215;
public static void main(String[] args) throws IOException {
server = new Server();
server.start();
server.bind(PORT);
server.addListener(new TheServer());
System.out.println("server started on " + PORT);
}
public void connected(Connection c) {
System.out.println("connected: " + c.getID());
}
public void disconnected(Connection c) {
System.out.println("disconnected: " + c.getID());
}
}
Client
public class TheClient extends Listener {
static Client client;
static final String IP = "localhost";
static final int PORT = 8215;
public static void main(String[] args) throws IOException {
client = new Client();
client.start();
client.connect(5000, IP, PORT);
client.addListener(new TheClient());
//client.setKeepAliveTCP(2000);
}
}
After running TheServer and then TheClient, my console prints:
server started on 8215
connected: 1
disconnected: 1
Note that the time between the connection and disconnection is almost immediate, certainly less than the connection timeout time I set. Also note that I commented out the setKeepAliveTCP() method because while I do not think it is necessary, I inserted it to see if it would work.
After some more digging around, I found that starting the client with:
new Thread(client).start()
instead of
client.start()
fixes the problem.
"Starting with r122, client update threads were made into daemon threads, causing the child processes to close as soon as they finish initializing."
Related
I'm creating a plugin on a certain platform (the details are irrelevant) and need to create a HTTP endpoint. In normal circumstances you'd create a http server and stop it whenever you're done using it or when the application stops, however, in my case I can't detect when the plugin is being uninstalled/reinstalled.
The problem
When someone installs my plugin twice, the second time it will throw an error because I'm trying to create a http server on a port which is already in use. Since it's being reinstalled, I can't save the http server on some static variable either. In other words, I need to be able to stop a previously created http server without having any reference to it.
My attempt
I figured the only way to interact with the original reference to the http server would be to create a thread whenever the http server starts, and then overwrite the interrupt() method to stop the server, but somehow I'm still receiving the 'port is already in use' error. I'm using Undertow as my http server library, but this problem applies to any http server implementation.
import io.undertow.Undertow;
import io.undertow.util.Headers;
public class SomeServlet extends Thread {
private static final String THREAD_NAME = "some-servlet-container-5391301";
private static final int PORT = 5839;
private Undertow server;
public static void listen() { // this method is called whenever my plugin is installed
deleteExistingServer();
new SomeServlet().start();
}
private static void deleteExistingServer() {
for (Thread t : Thread.getAllStackTraces().keySet()) {
if (t.getName().equals(THREAD_NAME)) {
t.interrupt();
}
}
}
#Override
public void run() {
createServer();
}
#Override
public void interrupt() {
try {
System.out.println("INTERRUPT");
this.server.stop();
} finally {
super.interrupt();
}
}
private void createServer() {
this.server = Undertow.builder()
.addHttpListener(PORT, "localhost")
.setHandler(exchange -> {
exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain");
exchange.getResponseSender().send("Hello World!");
})
.build();
this.server.start();
}
}
Desired behaviour
Whenever listen() is called, it will remove any previously existing http server and create a new one, without relying on storing the server on a static variable.
You could try com.sun.net.httpserver.HttpServer. Use http://localhost:8765/stop to stop and 'http://localhost:8765/test' for test request:
import com.sun.net.httpserver.HttpServer;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
public class TestHttpServer {
public static void main(String[] args) throws IOException {
final HttpServer server = HttpServer.create();
server.bind(new InetSocketAddress(8765), 0);
server.createContext("/test", httpExchange -> {
String response = "<html>TEST!!!</html>";
httpExchange.sendResponseHeaders(200, response.length());
OutputStream os = httpExchange.getResponseBody();
os.write(response.getBytes());
os.close();
});
server.createContext("/stop", httpExchange -> server.stop(1));
server.start();
}
}
Version
vert.x core: 3.3.0
Context
Am just trying to run http client in core examples io.vertx.example.core.http.simple.Client.
While running this example its found that the established connection not closing after completion of request.
Server side I didnt see any issue. Since while trying with jmeter and server its working fine. So I think that the problem is in the HttpClient.
Anyone can help me on this?
Thanks in advance.
Steps to reproduce
running io.vertx.example.core.http.simple.Server code
running io.vertx.example.core.http.simple.Client code
Extra
The following shown even after the request and response is ended. while giving
LINUX
lsof -i -P
java 32551 USER 223u IPv4 16264097 0t0 TCP localhost:8080->localhost:26980 (ESTABLISHED)
java 32634 USER 218u IPv4 16264087 0t0 TCP localhost:26980->localhost:8080 (ESTABLISHED)
WINDOWS
TCP 127.0.0.1:8080 FSSCHND12957:56893 ESTABLISHED
TCP 127.0.0.1:56893 FSSCHND12957:8080 ESTABLISHED
Tried in both LINUX and WINDOWS system.
Client Code
package io.vertx.example.core.http.simple;
import io.vertx.core.AbstractVerticle;
import io.vertx.example.util.Runner;
/*
#author Tim Fox
*/
public class Client extends AbstractVerticle {
// Convenience method so you can run it in your IDE
public static void main(String[] args) {
Runner.runExample(Client.class);
}
#Override
public void start() throws Exception {
vertx.createHttpClient().getNow(8080, "localhost", "/", resp -> {
System.out.println("Got response " + resp.statusCode());
resp.bodyHandler(body -> {
System.out.println("Got data " + body.toString("ISO-8859-1"));
});
});
}
}
Server Code
package io.vertx.example.core.http.simple;
import io.vertx.core.AbstractVerticle;
import io.vertx.example.util.Runner;
/*
#author Tim Fox
*/
public class Server extends AbstractVerticle {
// Convenience method so you can run it in your IDE
public static void main(String[] args) {
Runner.runExample(Server.class);
}
#Override
public void start() throws Exception {
vertx.createHttpServer().requestHandler(req -> {
req.response().putHeader("content-type", "text/html").end("
Hello from vert.x!
");
}).listen(8080);
}
}
We have to close the httpClient which we normally do in java. Only end() is not closing the connection. httpClient.close() is required.... This solved my issue..
Modified code:
public class Client extends AbstractVerticle {
// Convenience method so you can run it in your IDE
public static void main(String[] args) {
Runner.runExample(Client.class);
}
#Override
public void start() throws Exception {
HttpClient httpClient = vertx.createHttpClient().getNow(8080, "localhost", "/", resp -> {
System.out.println("Got response " + resp.statusCode());
resp.bodyHandler(body -> {
System.out.println("Got data " + body.toString("ISO-8859-1"));
httpClient.close();
});
});
}
}
I have a problem that's driving me crazy.
Let's say I have client and server (TCP connection):
public class ServerTCP {
public static void main(String args[]) throws IOException {
ServerSocket srvr = new ServerSocket(4380);
Socket skt = srvr.accept();
System.out.print("Client has connected!\n");
skt.close();
srvr.close();
}
}
public class ClientTCP {
public static void main(String args[]) throws IOException {
Socket skt = new Socket("myIPaddress", 4380);
}
}
If I replace IP address from ClientTCP with "localhost", everything works fine. When I start ServerTCP, go to http://www.yougetsignal.com/tools/open-ports/, enter 4380 and hit Check, I got message from terminal "Client has connected!". So that should mean that port forwarding is right and I can receive connections. But, when I try to connect from ClientTCP I cannot do it. No matter what I do (disabled ufw, tried different ports), it's just stuck and I eventually I get connection timeout.
I also tried same thing with Netty, same problem occurs. I am using XUbuntu
16.04 LTS, if that helps. I have no idea what else should I do.
This question already has an answer here:
Java Multiple threads for just 2 computers, how to do it in main
(1 answer)
Closed 7 years ago.
public class SOCKET_SERVER {
private JmailHelp JmailHELPER = new JmailHelp();
static int PORT = 444;
public static void main(String[] args) throws Exception {
SOCKET_SERVER SERVER = new SOCKET_SERVER();
SERVER.JmailHELPER.resetONN();
ServerSocket SRVSOCK = new ServerSocket(PORT);
//ArrayList<SocketStatus> OnlineUsers = new ArrayList<SocketStatus>();
Socket SOCK = SRVSOCK.accept();
//new ServerThread(SOCK).start();
SocketStatus a = new SocketStatus(SOCK, false);
//OnlineUsers.add(a);
//String action = "";
SERVER.ServerActionsHandler(SERVER, SRVSOCK, SOCK, a);
}//
}
forgive me if what i am giving is not enough don't hesitate to ask more if you can and want to try to help me
Well,
this is my socket server class ServerActionHandler is a method i created that takes as "input"(by BufferedReader) from the client a string and calls the right methods to serve the client.
for example he wants to login:
he(client) sends the string "login"
then server takes it as an "input" by the ServerActionHandler in a string called action, then recognise the the "login" and then calls the Acceptlogin method from the server class
Meanwhile client who send the "logi message" is calling the Dologin method from the client class
4.a loop of the ServerActionsHandler ends
5.A new loop starts asking the new action from the Client
my project works for A server and One client
I want to make it working for many clients
also something more I use JmailHELPER object
in almost all the methods of SOCKET_SERVER class(eg. login_accept,register_accept...)
in order to call some methods of it's class.
And SocketStatus keeps one variable if the certain socket which uses the Server is logged in or not
from what I know i have to make a ServerThreads class that extends Threads to handle more than one users.
What is the constructor and the run of that classmethod supposed to do
for example of A SocketThread I have this http://www.cdk5.net/ipc/programCode/TCPServer.java
thanks.
ok,
I know its funny but after a break of two hours I tried to find the solution for 3 minutes and i solved it(thats what i believe for now :P )
At least it is working on my pc for two clients so I will check it tommorow in more than one pc
Anyway I am posting the answer to my problem so that you can see it if you have a common problem
public static void main(String[] args) throws Exception {
SOCKET_SERVER SERVER = new SOCKET_SERVER();
SERVER.JmailHELPER.resetONN();
ServerSocket SRVSOCK = new ServerSocket(PORT);
while (true) {
Socket SOCK = SRVSOCK.accept();
SocketStatus a = new SocketStatus(SOCK, false);
new Thread() {
public void run() {
try {
SERVER.ServerActionsHandler(SERVER, SRVSOCK, SOCK, a);
} catch (Exception ex) {
Logger.getLogger(SOCKET_SERVER.class.getName()).log(Level.SEVERE, null, ex);
};
}
}.start();
}
}
My question is about creating multiple TCP clients to multiple hosts using the same event loop group in Netty 4.0.23 Final, I must admit that I don't quite understand Netty 4's client threading business, especially with the loads of confusing references to Netty 3.X.X implementations I hit through my research on the internet.
with the following code, I establish a connection with a single server, and send random commands using a command queue:
public class TCPsocket {
private static final CircularFifoQueue CommandQueue = new CircularFifoQueue(20);
private final EventLoopGroup workerGroup;
private final TcpClientInitializer tcpHandlerInit; // all handlers shearable
public TCPsocket() {
workerGroup = new NioEventLoopGroup();
tcpHandlerInit = new TcpClientInitializer();
}
public void connect(String host, int port) throws InterruptedException {
try {
Bootstrap b = new Bootstrap();
b.group(workerGroup);
b.channel(NioSocketChannel.class);
b.remoteAddress(host, port);
b.handler(tcpHandlerInit);
Channel ch = b.connect().sync().channel();
ChannelFuture writeCommand = null;
for (;;) {
if (!CommandQueue.isEmpty()) {
writeCommand = ch.writeAndFlush(CommandExecute()); // commandExecute() fetches a command form the commandQueue and encodes it into a byte array
}
if (CommandQueue.isFull()) { // this will never happen ... or should never happen
ch.closeFuture().sync();
break;
}
}
if (writeCommand != null) {
writeCommand.sync();
}
} finally {
workerGroup.shutdownGracefully();
}
}
public static void main(String args[]) throws InterruptedException {
TCPsocket socket = new TCPsocket();
socket.connect("192.168.0.1", 2101);
}
}
in addition to executing commands off of the command queue, this client keeps receiving periodic responses from the serve as a response to an initial command that is sent as soon as the channel becomes active, in one of the registered handlers (in TCPClientInitializer implementation), I have:
#Override
public void channelActive(ChannelHandlerContext ctx) {
ctx.writeAndFlush(firstMessage);
System.out.println("sent first message\n");
}
which activates a feature in the connected-to server, triggering a periodic packet that is returned from the server through the life span of my application.
The problem comes when I try to use this same setup to connect to multiple servers,
by looping through a string array of known server IPs:
public static void main(String args[]) throws InterruptedException {
String[] hosts = new String[]{"192.168.0.2", "192.168.0.4", "192.168.0.5"};
TCPsocket socket = new TCPsocket();
for (String host : hosts) {
socket.connect(host, 2101);
}
}
once the first connection is established, and the server (192.168.0.2) starts sending the designated periodic packets, no other connection is attempted, which (I think) is the result of the main thread waiting on the connection to die, hence never running the second iteration of the for loop, the discussion in this question leads me to think that the connection process is started in a separate thread, allowing the main thread to continue executing, but that's not what I see here, So what is actually happening? And how would I go about implementing multiple hosts connections using the same client in Netty 4.0.23 Final?
Thanks in advance