I coded a server application that constantly listens to data being sent to it. I took multi-threading into consideration by the way. I have the main thread, writer thread, and reader thread. When I launch the program, everything works perfectly. After about 15 minutes of up-time though, my CPU usage just randomly skyrockets. I believe it reaches about 40% just for the server application if I remember correctly. I think I'm doing something wrong with networking since this is my first time working with sockets.
This is what I use to read data:
public void run(){
Socket s = null;
InputStream in = null;
while (Main.running){
try {
s = network.getServerSocket().accept();
in = s.getInputStream();
} catch (IOException e){
e.printStackTrace();
}
if (in != null){
DataInputStream input = new DataInputStream(in);
try {
while (input.available() != -1) {
byte type = input.readByte();
PacketIn packet = Utils.getPacket(main, type);
packet.readData(input);
if (packet instanceof PacketInLogin) {
PacketInLogin login = (PacketInLogin) packet;
login.setSocket(s);
String server = login.getServer();
Socket socket = login.getSocket();
Main.log("Login request from server: '" + server + "'. Authenticating...");
boolean auth = login.authenticate();
Main.log("Authentication test for server: '" + server + "' = " + (auth ? "PASSED" : "FAILED"));
if (auth) {
main.getServers().put(server, new DataBridgeServer(main, server, socket));
}
main.getTransmitter().sendPacket(new PacketOutAuthResult(main, auth), socket);
} else if (packet instanceof PacketInDisconnect) {
PacketInDisconnect disconnect = (PacketInDisconnect) packet;
main.getServers().remove(disconnect.getServer().getName());
Main.log("'" + disconnect.getServer().getName() + "' has disconnected from network.");
}
}
} catch (IOException e){
if (!(e instanceof EOFException)){
e.printStackTrace();
}
} finally {
if (in != null){
try {
in.close();
} catch (IOException e){
e.printStackTrace();
}
}
}
}
}
try {
if (s != null) s.close();
if (in != null) in.close();
} catch (IOException e){
e.printStackTrace();
}
}
This is what I use to write data (to the client. This code is still part of the server):
public void run(){
while (Main.running){
if (!QUEUED.isEmpty()){
PacketOut packet = (PacketOut) QUEUED.keySet().toArray()[0];
Socket server = QUEUED.get(packet);
DataOutputStream out = null;
try {
out = new DataOutputStream(server.getOutputStream());
packet.send(out);
} catch (IOException e){
e.printStackTrace();
} finally {
if (out != null){
try {
out.close();
} catch (IOException e){
e.printStackTrace();
}
}
}
QUEUED.remove(packet);
}
}
}
Related
I am trying to connect to the tcp client and I keep getting ioexception connection refused error. I don't know what I am doing wrong. I am trying to enable tcp notification. I am connecting to a rfid reader and trying to get the data back to my program to insert in a database.
Here is my code:
Socket tagServerSocket;
while (true){
try{
String data;
tagServerSocket = new Socket("localhost", this.notifyPort);
DataOutputStream outToServer = new
DataOutputStream(tagServerSocket.getOutputStream());
while (true) {
try {
Thread.sleep(20);
} catch (Exception e) {
System.err.println(e.getMessage());
}
int cnt_rd=0;
while((cnt_rd < 10) && (TagBuffer.size() > 0))
{
synchronized (TagBuffer) {
if (TagBuffer.size() != 0) {
data = "";
TagInfo tag = TagBuffer.peek();
data += "ReaderIP:" + tag.ipaddr;
data += "|ID:" + tag.epc;
data += "|Antenna:" + tag.antennaPort;
data += "|Timestamp:" + tag.timestamp;
data += "|PC:" + tag.pc;
data += "|RSSI:" + tag.rssi + "\n";
TagBuffer.remove();
outToServer.writeBytes(data);
cnt_rd++;
}
}
}
}
tagServerSocket.close();
tagServerSocket = null;
Thread.sleep(10);
startup=true;
} catch (UnknownHostException e) {
tagServerSocket = null;
startup=false;
System.out.println("Unable to connect to port " +
this.notifyPort);
} catch (IOException e) {
// tagServerSocket = null;
startup=false;
String data1 = String.format("00");
System.out.println("Unable to send tag data to server" +
data1);
System.out.println("ioexception tcpclient:
"+e.getMessage());
} catch (InterruptedException e) {
startup=false;
e.printStackTrace();
}
}
I made a multiplayer snake game which is sending the actual score and health to the opponent over socket. The problem is during the game, the enemies health will be its score.
Example the enemy has 90 health and 15 score. When the enemy get 1 score it health will be 16 and the score remains 15. I think the problem is somewhere in the server:
private boolean listenForServerRequest() {
Socket socket = null;
try {
socket = serverSocket.accept();
dos = new DataOutputStream(socket.getOutputStream());
dos2 = new DataOutputStream(socket.getOutputStream());
dis = new DataInputStream(socket.getInputStream());
dis2 = new DataInputStream(socket.getInputStream());
accepted = true;
System.out.println("Client has requested and joined the game");
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
private boolean connect() {
try {
socket = new Socket(ip, port);
dos = new DataOutputStream(socket.getOutputStream());
dos2 = new DataOutputStream(socket.getOutputStream());
dis = new DataInputStream(socket.getInputStream());
dis2 = new DataInputStream(socket.getInputStream());
accepted = true;
} catch (IOException e) {
System.out.println("Unable to connect to the address: " + ip + ":" + port + " | Starting a server");
return false;
}
System.out.println("Successfully connected to the server.");
return true;
}
private void initializeServer() {
try {
serverSocket = new ServerSocket(port, 8, InetAddress.getByName(ip));
} catch (Exception e) {
e.printStackTrace();
}
}
public boolean getConnected() {
return this.connected;
}
public void sendHealth(SnakeHead snakeHead) {
try {
dos.writeInt(snakeHead.getHealth());
System.out.println(snakeHead.getHealth());
dos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendScore(SnakeHead snakeHead) {
try {
dos2.writeInt(Globals.getScore());
System.out.println(snakeHead.getHealth());
dos2.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public int getEnemyHealth() {
try{if (dis.available() != 0 ) {
try {
enemyHealth = dis.readInt();
return enemyHealth;
} catch (IOException e) {
e.printStackTrace();
}
}}catch (IOException e){
e.printStackTrace();
}
return enemyHealth;
}
public int getEnemyScore() {
try{if (dis2.available() != 0) {
try {
enemyScore = dis2.readInt();
return enemyScore;
} catch (IOException e) {
e.printStackTrace();
}
}}catch (IOException e){
e.printStackTrace();
}
return enemyScore;
}
Hope someone will find the problem or has any advice! Thanks!
Sending multiple data is not a problem. Socket works in TCP mode in this example so write order = read order. To avoid serialization, I would suggest you to send separated values in form of String and use PrintWriter for this purpose. This would send data in "one shot"
See this example:
try (
Socket echoSocket = new Socket(hostName, portNumber);
PrintWriter out =
new PrintWriter(echoSocket.getOutputStream(), true);
BufferedReader in =
new BufferedReader(
new InputStreamReader(echoSocket.getInputStream()));
// reading
String userInput;
while ((userInput = stdIn.readLine()) != null) {
System.out.println("echo: " + in.readLine());
}
// writing
out.println(int + "," + int); // multiple data
)
With socket.getOutputStream() you will get the same stream each time
You have to send the data in a struct , containing the score and health, or you have to send them separately in sequence (like first the health then the score or vicevesa)
I'm working on a little game that sends location data between a client an server to learn how Sockets work.
The server can send and receive data no problem, and the client can send data, but when the client tries to read in data from the server, the program hangs. (This part is commented out)
Server Code:
public void run() {
try {
serverSocket = new ServerSocket(10007);
} catch (IOException e) {
System.err.println("Could not listen on port: 10007.");
System.exit(1);
}
try {
System.out.println("Waiting for connection...");
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
System.out.println("Connection successful");
System.out.println("Waiting for input.....");
while (true) {
try {
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
out = new PrintWriter(clientSocket.getOutputStream(), true);
if (in.readLine() != "0" && in.readLine() != null) {
setXY(in.readLine());
}
} catch (IOException e) {
e.printStackTrace();
}
out.println("X" + Graphics.charX);
out.println("Y" + Graphics.charY);
}
Client Code:
public void run() {
try {
System.out.println("Attemping to connect to host " + serverHostname + " on port " + serverPort + ".");
echoSocket = new Socket(serverHostname, serverPort);
} catch (UnknownHostException e) {
System.err.println("Don't know about host: " + serverHostname);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for " + "the connection to: " + serverHostname);
System.exit(1);
}
while (true) {
try {
in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
out = new PrintWriter(echoSocket.getOutputStream(), true);
/*if (in.readLine() != "0" && in.readLine() != null) {
setXY(in.readLine());
}*/
} catch (IOException e2) {
e2.printStackTrace();
}
out.println("X" + Graphics.charX);
out.println("Y" + Graphics.charY);
}
}
Any help is much appreciated!
You need two threads to read/write blocking sockets at the same time (which is what you're trying to do). When you call in.readLine(), the current thread will block until it receives a line of data.
I made a simple app works with socket to transfer data between client and server over local network,
Server java codes:
try {
serverSocket = new ServerSocket(8888);
System.out.println("Listening :8888");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while (true) {
try {
socket = serverSocket.accept();
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream = new DataOutputStream(
socket.getOutputStream());
System.out.println("ip: " + socket.getInetAddress());
String message = dataInputStream.readUTF();
// System.out.println("message: " + dataInputStream.readUTF());
try {
JSONObject jObj = new JSONObject(message);
String flag = jObj.getString("flag");
if (flag.equals("request")) {
String request = jObj.getString("request");
if (request.equals("getGroup"))
dataOutputStream.writeUTF(getGroup());
else if (request.equals("getFood")) {
String groupID = jObj.getString("groupID");
dataOutputStream.writeUTF(getFood(groupID));
}
}
} catch (JSONException | IOException e) {
e.printStackTrace();
}
// dataOutputStream.writeUTF("Hello!");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataOutputStream != null) {
try {
dataOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
and android client codes:
class Load extends AsyncTask<String, String, String> {
String response;
#Override
protected void onPreExecute() {
super.onPreExecute();
}
protected String doInBackground(String... args) {
Socket socket = null;
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream = null;
try {
socket = new Socket("192.168.1.106", 8888);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream.writeUTF(utils.getGroup());
response = dataInputStream.readUTF();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataOutputStream != null) {
try {
dataOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
protected void onPostExecute(String file_url) {
showGroup(response);
}
}
How many clients this can handle?
Is there a better solution?
How many clients this can handle?
Basically your code is an iterative server. There’s one big loop, and in each pass through the loop a single connection is completely processed.
A: So in this sense it can handle only one client at a time.
If you want to suport more than one client at a time your server should service multiple clients simultaneously through the use of threads (one thread per each client connection).
The basic flow of logic in such a server is this:
while (true) {
accept a connection;
create a thread to deal with the client;
}
Please refer to the following tutorial for a full explanation and even some code example.
Is there a better solution?
In the Android side, as pointed out in my comment based in the answer here. Using AsyncTask for HTTP communications can have some drawbacks like:
You cannot cancel a request during execution.
The patterns of using AsyncTask also commonly leak a reference to an Activity...
A: A library like OkHttp can apply as a more robust alternative.
I want to know if is possible to close the current java app util another has done some task, my code is this:
private static void callJar(String jardir) throws IOException, InterruptedException {
// jardir contains the excecution command
Process p = Runtime.getRuntime().exec(jardir);
synchronized (p) {
// Here I want to wait for p for a signal but not when p has finished
// but waitFor() do the second
p.waitFor();
}
// If the other jar is correctly loaded, close this jar
System.exit(0);
}
The string jardir contains the excecution command that will start the other process that I will be listening, something like this:
jardir = "javaw -jar \\path\\to\\anotherjar.jar"
For now, callJar() opens this process and then close the current until the process that I started has been terminated. In other words, close A until B has been closed.
But what I want to do is to close A until B send a signal (B will continue to exist).
Is there a way to listen for a signal from the process that I started?
After searching for an answer, I finally found a solution, maybe this will work for someone so here is what I did:
Based on this answer and this site, I opted to create a communication between two Java apps using the java.net libraries.
In the process A, I have a method that create a server communication and just waits until it receive a message from process B...
private static boolean listen2ExternalProcess() {
ServerSocket server = null;
Socket serverSocked = null;
String line;
BufferedReader inputReader = null;
try {
server = new ServerSocket(3333);
serverSocked = server.accept();
inputReader = new BufferedReader(
new InputStreamReader(serverSocked.getInputStream()));
while (true) {
line = inputReader.readLine();
log.info("Client says: " + line);
if (line.equals("Kill yourself :D")) {
return true;
}
}
} catch (UnknownHostException e) {
log.error("Don't know about this, " + e);
return false;
} catch (IOException e) {
log.error("Couldn't get IO for the connection, " + e);
return false;
} finally {
try {
if(serverSocked != null) serverSocked.close();
if(inputReader != null) inputReader.close();
} catch (IOException ex) {
log.error("Couldn't get IO for the connection, " + ex);
return false;
}
}
}
this method will return true if the message has been received, then I can proceed to terminate process A.
In the process B, I have a method that just send a message to a socket when I need it...
public static void talk2ExternalProcess() {
Socket socket = null;
BufferedWriter outputWriter = null;
try {
socket = new Socket("localhost", 3333);
outputWriter = new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream()));
} catch (UnknownHostException e) {
log.error("Don't know about host: localhost, " + e);
} catch (IOException e) {
log.error("Couldn't get IO for the connection to localhost, " + e);
}
if (socket != null && outputWriter != null) {
try {
outputWriter.write("Kill yourself :D");
} catch (UnknownHostException e) {
log.error("Trying to connect to unkown host: " + e);
} catch (IOException e) {
log.error("IO Exception: " + e);
} finally {
try {
outputWriter.close();
socket.close();
} catch (IOException ex) {
log.error("IO Exception: " + ex);
}
}
} else {
log.warn("null socket or outputwriter");
}
}
finally, I just change the callJar method to something like this:
private static void callJar(String jardir) throws IOException {
Runtime.getRuntime().exec(jardir);
if (listen2ExternalProcess()) {
System.exit(0);
} else {
log.warn("Something went wrong...");
}
}
I would like to find an easier answer, but for now, this works for me.