Socket inside bukkit plugin closes after use - java

I am trying to open a socket inside a bukkit plugin so i could send data to it using php or node but instead of socket remaining open after one use it just closes and also server does not load before this happens what should i do i am out of ideas.
Main:
public class Main extends JavaPlugin {
public void onEnable() {
saveDefaultConfig();
getConfig().options().copyDefaults(true);
System.out.println("[INFO] Main class loaded.");
start();
}
public void start() {
SocketServer server = new SocketServer();
try {
server.start(getConfig().getInt("port"), getConfig().getString("socket-password"));
System.out.println("[INFO] Main successfully called start.");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Socket server class:
When called this should read information convert it into array check the first item in array and use it as auth code then array should be converted into string and used in Command executor class. This works fine but after one use this just closes
public class SocketServer {
private ServerSocket serverSocket;
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
public void start(int port, String socketpwd) throws IOException {
System.out.println("[INFO] Socket server listening on: " + port);
serverSocket = new ServerSocket(port);
clientSocket = serverSocket.accept();
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
Boolean enabled = true;
try {
// Socket authentication
String message = in.readLine();
String suffix[] = message.split(" ");
System.out.println("Socket auth code used: "+ suffix[0]);
System.out.println("Socket pwd is: " + socketpwd);
if (socketpwd.equals(suffix[0])) {
out.println("Auth sucessfull!");
// do the following command from args here
String command = suffix[1];
int suffixL = suffix.length;
// add arguments to command
for (int i = 2; i < suffixL; i++) {
command = command + " " + suffix[i];
}
// call req exec
System.out.println("[INFO] Socket server contacted Request executor with: " + command);
RequestExecutor.executor(command);
enabled = false;
}
else {
out.println("Unrecognised auth code!");
}
} catch (NullPointerException e) {
System.out.println("Exception prevented!");
}
}
public void stop() throws IOException {
in.close();
out.close();
clientSocket.close();
serverSocket.close();
}
}
Other problem as i mentioned is that bukkit server does not fully load before one request has been made to this socket.
Thank you for your help.

First of all you shouldn't be running a socket like that on the main thread, typically you should be running this on an async task using the Bukkit scheduler.
Then once you open the socket you should create a while loop to continuously poll for a connection and handle the incoming data. Instead what you are doing is opening the socket, reading a line and then dropping the connection.
You want to be doing something similar to
while(true){
Socket socket = serverSocket.accept();
}
See this webpage for some more info.

Related

Java Simple Client Server application

Im sorry I am coding 12 hours now and now I have a "brainlag".
I made a little Client Server programm.
Client:
public void send(String send) {
DataOutputStream out;
Socket client;
try {
client = new Socket("192.168.0.138", port);
out = new DataOutputStream(client.getOutputStream());
out.writeChars(send + '\n');
Thread.sleep(100L);
} catch (IOException ex) {
System.err.println("Can't connect to Server!");
} catch (InterruptedException ex) {
System.err.println("Cant sleep!");
}
}
Server:
public static void main(String[] args) throws IOException {
int port = 5000;
String cIn;
System.out.println("Running on Port 5000");
ServerSocket sock = new ServerSocket(port);
Socket client;
BufferedReader inFromClient;
while (true) {
client = sock.accept();
inFromClient = new BufferedReader(new InputStreamReader(client.getInputStream()));
cIn = inFromClient.readLine();
System.out.println("" + cln);
}
}
Now my question. How can i make it that my string (data) is sending in a loop to the server while I input a new data.
If a make a normal while loop, my string is sending permanently to the server. If i change my String it doesn't matter.
I would make it that if i change my String, that the new String is sending to the server.
I'm sorry for my bad english. I hope you will understand.
how about sending the data with a new thread whichs sends the data in a loop. when you input some new data interupt the old thread and start a new one and so on?
I think you need to add a bufferedReader close at the end of the while loop.
while (true) {
client = sock.accept();
inFromClient = new BufferedReader(new InputStreamReader(client.getInputStream()));
cIn = inFromClient.readLine();
System.out.println("" + cln);
inFromClient.close() //add this
}
If I resume:
- you need a console app (or window/awt/swing ...) or main client app which take a String, and sometimes change this String.
- this String must be sent by your function "send", continuously, with the last String
I propose you:
1 - to fix the loop (1 sec, 2, sec, x seconds ?)
2 - to use a share variable (in critical section, or synchronized), your main client app writes it, and changes it when you want, and your "send" function read it every x seconds and sends it.
Your client could look like that:
// SHARED VARIABLE
static String warning="";
final static Object warning_sync=new Object();
// Alert function
class Thread_alert extends Thread
{
// YOUR CODE
public void send(String send) {
DataOutputStream out;
Socket client;
int port=80;
try {
client = new Socket("192.168.0.138", port);
out = new DataOutputStream(client.getOutputStream());
out.writeChars(send + '\n');
Thread.sleep(100L);
} catch (IOException ex) {
System.err.println("Can't connect to Server!");
} catch (InterruptedException ex) {
System.err.println("Cant sleep!");
}
}
public Thread_alert()
{
super();
}
public void run()
{
while (true)
{
// WHAT YOU HAVE TO DO
synchronized(warning_sync)
{
System.err.println("WARN: "+warning);
send(warning);
}
// Sleep 5 seconds
try {
Thread.sleep(5000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
// while (true)
}
// public void run()
}
// class Thread_alert
public void console_client ()
{
// START THE THREAD
Thread_alert lethread=new Thread_alert();
lethread.start();
// INPUT LOOP
Scanner s = new Scanner(System.in);
String line;
while ((line=s.nextLine())!=null)
{
System.out.println("STRING:'"+line+"'");
// Fix the warning
synchronized(warning_sync)
{
warning=line;
}
// bonus
// IF STOP: STOP
if (warning.equals("STOP"))
{
lethread.stop();
break;
}
}
// while ((line=s.nextLine())!=null)
// safe
s.close();
}

Socket Connection on Java, specify IP

I'm working on a program where multiple clients need to interact with a remote server.
I've tested it locally and everything's ok (sort of, more on that later), but I can't understand how to set a remote IP.
I read Socket's API and also InetAddress' API. Is this the right way to do it? How does Java deal with IPs? There are not just simple Strings as on the localhost case, am I right?
This is my code:
Client:
public class Client {
final String HOST = "localhost";
final int PORT = 5000;
Socket sc;
DataOutputStream message;
DataInputStream istream;
public void initClient() {
try {
sc = new Socket(HOST, PORT);
message = new DataOutputStream(sc.getOutputStream());
message.writeUTF("test");
sc.close();
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
}
Server:
public class Server {
final int PORT = 5000;
ServerSocket sc;
Socket so;
DataOutputStream ostream;
String incomingMessage;
public void initServer() {
try {
sc = new ServerSocket(PORT);
} catch (IOException ex) {
System.out.println("Error: " + ex.getMessage());
}
BufferedReader input;
while(true){
try {
so = new Socket();
System.out.println("Waiting for clients...");
so = sc.accept();
System.out.println("A client has connected.");
input = new BufferedReader(new InputStreamReader(so.getInputStream()));
ostream = new DataOutputStream(so.getOutputStream());
System.out.println("Confirming connection...");
ostream.writeUTF("Successful connection.");
incomingMessage = input.readLine();
System.out.println(incomingMessage);
sc.close();
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
}
}
Also, I'm dealing with some troubles on my local tests.
First of all, some times I get the following result:
Waiting for clients...
A client has connected.
Confirming connection...
Error: Software caused connection abort: recv failed
Though some other times it works just fine. Well, that first connection at least.
Last question:
When I try to send a message from the server to the client, the program enters in an infite loop and need to be closed manually. I'm adding this to the code to do so:
fromServerToClient = new BufferedReader(new InputStreamReader(sc.getInputStream()));
text = fromServerToClient.readLine();
System.out.println(text);
Am I doing it right?
Thanks.
Instead of using
String host = "localhost";
you can use something like
String host = "www.ibm.com";
or
String host = "8.8.8.8";
this is how you would usually implement a Server:
class DateServer {
public static void main(String[] args) throws java.io.IOException {
ServerSocket s = new ServerSocket(5000);
while (true) {
Socket incoming = s.accept();
PrintWriter toClient =
new PrintWriter(incoming.getOutputStream());
toClient.println(new Date());
toClient.flush();
incoming.close();
}
}
}
And following would be As Client:
import java.util.Scanner;
import java.net.Socket;
class DateClient {
public static void main(String[] args) throws java.io.IOException
{
String host = args[0];
int port = Integer.parseInt(args[1]);
Socket server = new Socket(host, port);
Scanner scan = new Scanner( server.getInputStream() );
System.out.println(scan.nextLine());
}
}
You should consider doing this in threads. Right now multiple users can't connect to the server at once. This means that they have to queue for connection to the server resulting in very poor performance.
Normally you receive the client and instantiate a new thread to handle the clients request. I only have exampls in C# so i won't bother you with that, but you can easily find examples on google.
eg.
http://www.kieser.net/linux/java_server.html

Client-Server connection

I have a java program that will connect the client to the server.
This includes making a file directory once the client had triggered the server through sending a message. For example: Once the server is running already, the client will then connect and will send a msg i.e "Your message: Lady", the server will receive a message like "Request to create a Directory named: Lady", after this a directory will be created named Lady.
But the problem is this connection is only for one-to-one. Like only one client can connect to the server...
This is the sample code:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package today._;
import java.io.*;
import java.net.*;
import java.text.*;
import java.util.*;
public class myServer {
protected static final int PORT_NUMBER = 55555;
public static void main(String args[]) {
try {
ServerSocket servsock = new ServerSocket(PORT_NUMBER);
System.out.println("Server running...");
while (true) {
Socket sock = servsock.accept();
System.out.println("Connection from: " + sock.getInetAddress());
Scanner in = new Scanner(sock.getInputStream());
PrintWriter out = new PrintWriter(sock.getOutputStream());
String request = "";
while (in.hasNext()) {
request = in.next();
System.out.println("Request to Create Directory named: " + request);
if(request.toUpperCase().equals("TIME")) {
try {
File file = new File("C:\\" + request);
if (!file.exists()) {
if (file.mkdir()) {
System.out.println("Directory is created!");
} else {
System.out.println("Failed to create directory!");
}
}
} catch (Exception e) {
System.out.println(e);
}
out.println(getTime());
out.flush();
} else {
out.println("Invalid Request...");
out.flush();
}
}
}
} catch (Exception e) {
System.out.println(e.toString());
}
}
protected static String getTime() {
DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
Date date = new Date();
return (dateFormat.format(date));
}
}
package today._;
import java.io.*;
import java.net.*;
import java.util.*;
public class myClient {
protected static final String HOST = "localhost";
protected static final int PORT = 55555;
protected static Socket sock;
public static void main(String args[]) {
try {
sock = new Socket(HOST,PORT);
System.out.println("Connected to " + HOST + " on port " + PORT);
Scanner response = new Scanner(sock.getInputStream());
PrintWriter request = new PrintWriter(sock.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String txt = "";
while(!txt.toUpperCase().equals("EXIT")) {
System.out.print("Your message:");
txt = in.readLine();
request.println(txt);
request.flush();
System.out.println(response.next());
}
request.close();
response.close();
in.close();
sock.close();
} catch(IOException e) {
System.out.println(e.toString());
}
}
}
Multi-client servers are generally written one of two ways:
Create a thread for each client. To do this you would create a thread to handle the calls to accept() on the server socket and then spawn a new thread to handle calls on the Socket that it returns. If you do this, you need to make sure you isolate the code for each socket as much as possible. The accept thread will loop forever, or until a flag is set, and will just call accept, spawn a thread with the new socket, and go back to calling accept. All of the work is in the child thread.
Use NIO, or another technology, to multi-plex work into 1 more more threads. NIO uses a concept sometimes called select, where your code will be called when there is input available from a specific socket.
If you are just doing a small server, you can go with the simplest design and also won't have too many clients, so I would go with #1. If you are doing a big production server, I would look into a framework like netty or jetty that will help you do #2. NIO can be tricky.
In either case, be very careful with threads and the file system, you might not get the results you expect if you don't use a Lock from the concurrency package, or synchronize, or another locking scheme.
My final advice, be careful with having a client tell a server to do anything with the file system. Just saying, that is a dangerous thing to do ;-)
Your server class must use multiple threads to handle all connections:
class MyServer {
private ServerSocket servsock;
MyServer(){
servsock = new ServerSocket(PORT_NUMBER);
}
public void waitForConnection(){
while(true){
Socket socket = servsock.accept();
doService(socket);
}
}
private void doService(Socket socket){
Thread t = new Thread(new Runnable(){
public void run(){
while(!socket.isClosed()){
Scanner in = new Scanner(sock.getInputStream());
PrintWriter out = new PrintWriter(sock.getOutputStream());
String request = "";
// and write your code
}
}
});
t.start();
}
}

Why is this socket null?

I am creating a multi client chat server and i am pretty confident that it will work (Correct me if i'm wrong), I have the issue that on the socket that the client connects to is null so the connections can't be created because i use if(Socket != null) so i don't get errors but i will explain my layout real fast. The server starts with a starter class called (LaunchServer) that uses the class object ClientConnector as Minecraft and then starts the method runServer(). Here is the code for this class:
public class LaunchServer
{
public static void main(String[] args)
{
System.out.println("[Info] Running");
ClientConnector Minecraft = new ClientConnector();
Minecraft.runServer();
}
}
It's fairly simple. This brings us to the ClientConnector class. Here we start at the method runServer(). Right away we have a try catch block. in that block we print a message that the server is trying to connect to the port 1337. we then create a new ServerSocket called serversocket. We then send a message to the console saying that we have bound to port and that we are awaiting a connection. While true, we create a new Socket socket that equals ServerSocket.accept(); OMG fuck it. Heres the code. you know what it does...
import java.util.ArrayList;
import java.net.*;
import java.io.*;
public class ClientConnector
{
public static ArrayList<Socket> Connections = new ArrayList<Socket>();
public static void runServer()
{
try
{
System.out.println("[Info] Attempting to bind to port 1337.");
#SuppressWarnings("resource")
ServerSocket serversocket = new ServerSocket(1337);
System.out.println("[Info] Bound to port 1337.");
System.out.println("[Info] Waiting for client connections...");
while(true)
{
Socket socket = serversocket.accept();
new ClientHandler(socket).start();
Connections.add(socket);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
This takes us to the handler class:
import java.io.*;
import java.net.*;
public class ClientHandler extends Thread
{
Socket Socket;
public ClientHandler(Socket socket)
{
socket = Socket;
System.out.println("[Info] Client connected on port 1337.");
}
public void run()
{
while(true)
{
for(int i = 0; i < ClientConnector.Connections.size(); i++)
{
try
{
if(Socket != null)//This stays null...
{
ObjectOutputStream Output = new //These can't be created...
ObjectOutputStream(Socket.getOutputStream());
ObjectInputStream Input = new ObjectInputStream(Socket.getInputStream());
whileChatting(Input, Output);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
public static void sendMessage(String message, String returnedMessage, ObjectOutputStream out)
{
try
{
if(!message.isEmpty())
{
out.writeObject("\247c[Server]\247d " + message);
out.flush();
System.out.println("[Chat] Sent: " + message);
}
else
{
out.writeObject(returnedMessage);
System.out.println("[Chat] Sent: " + returnedMessage);
}
out.flush();
System.out.println("[Info] Fluching remaining data to stream.");
System.out.println("\n[Server] " + message);
}
catch(IOException ioException)
{
System.out.println("[Warning] Error: ioException # sendMessage line 76.");
}
}
public static void whileChatting(ObjectInputStream input, ObjectOutputStream output) throws IOException
{
String message = "";
do
{
try
{
message = (String) input.readObject();
System.out.println("\n" + message);
sendMessage("", message, output);
}
catch(ClassNotFoundException classNotFoundException)
{
System.out.println("[Warning] Error: ClassNotFoundException # whileChatting line 1-7.");
System.out.println("\n idk wtf that user sent!");
}
}while(!message.equals("/stop"));
}
}
Read the run method. There you will see the null problem
Would the connection get accepted then passed to the hander class? How can a null connection get accepted? My question is how can i fix this problem?
The problem is you've got a logic error due to un-recommended naming conventions. You shouldn't name variables with keywords, like your Socket variable, and each variable should have a distinguishable name. e.g. not socket1, socket2 but serverSocket, clientSocket because that will make it easier for you and anyone else to read and fix your code.
Change
Socket Socket;
to
Socket connectedSocket;
and in your constructor
socket = Socket;
to
connectedSocket = socket;
then finally, in your run() method change
if(Socket != null)
to
if(connectedSocket != null)

Java networking using threads, when one client leaves the other cannot communicate to the server

I'm trying to create a server in java which accepts clients. Currently, two clients can connect to the server. However, when one leaves the other client can no longer communicate with the server. I think the issue is that my clientSocket is created outside my thread, which means it must be declared as 'final' because I use an innerclass. However, if I move it into the thread it cannot create the clientSocket. Any ideas on how to fix this? Thanks in advance.
Comment: If I close the clientSocket when the client leaves it says "Broken Pipe" error because the clientSocket is final so it cannot be changed - ie the clientSocket is the same for both clients.
private BufferedWriter writer;
private LODGame game;
public Server(int port) throws Exception {
try{
// Listen on the given port.
serverSocket = new ServerSocket(port);
game = new LODGame();
}
catch(BindException e){
throw new Exception("Failed to create a server socket: "+
e.getMessage());
}
}
public Server(int port, String map) throws Exception {
try{
// Listen on the given port.
serverSocket = new ServerSocket(port);
game = new LODGame(map);
}
catch(BindException e){
throw new Exception("Failed to create a server socket: "+
e.getMessage());
}
}
public void run() throws Exception {
final ServerSocket serverSocket = getServerSocket();
while (true){
System.out.println("Listening for a client on port: "+
serverSocket.getLocalPort());
// Wait for a client to make contact.
final Socket clientSocket = serverSocket.accept();
// Contact ...
System.out.println("A client has arrived.");
Thread serverThread = new Thread(){
public void run(){
boolean quit = false;
while (!quit){
try{
// Wrap the input stream in a BufferedReader.
BufferedReader reader = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
// Wrap the output stream in a BufferedWriter.
writer = new BufferedWriter(
new OutputStreamWriter(clientSocket.getOutputStream()));
game.setWriter(writer);
game.startNewGame();
// Read lines until the client terminates.
String request = reader.readLine();
while(request != null){
// Write the length of the line as a String.
playerCommand(request);
request = reader.readLine();
}
}
catch(IOException e){
System.out.println("IOException talking to the client: "+
e.getMessage());
}
finally{
if(clientSocket != null){
System.out.println("The client has gone.");
break;
// Close the socket to the client.
//try
// {
// clientSocket.close();
// }
//catch(Exception e)
// {
// System.out.println("Error" + e.getMessage());
// System.exit(1);
// }
}
}
try
{
serverSocket.close();
}
catch(Exception e)
{
System.out.println("Error" + e.getMessage());
System.exit(1);
}
}
}
};
serverThread.start();
}
}
protected ServerSocket getServerSocket(){
return serverSocket;
}
// The socket on which the listening is done.
private final ServerSocket serverSocket;
No this has nothing to do with the clientSocket being final. Your problem is that you are closing the serverSocket in the client thread. You should be closing the clientSocket only at the end of the thread:
while (!quit) {
try {
...
} catch(IOException e){
System.out.println("IOException talking to the client: "+
e.getMessage());
} finally {
...
clientSocket.close();
}
// DON'T DO THIS: serverSocket.close();
}
The serverSocket should only be closed if accept() throws an Exception -- it should not be touched by the client thread at all.

Categories

Resources