I have a class A that accepts TCP connection and send this new socket to Thread B where data from that socket is received and sent.
Class A{
Class b = new B();
public void run()
{
b.start();
while(true){
Socket socket = serverSocket.accept();
if(socket==null || socket.isClosed())continue;
b.setSocket(socket);
}
}
}
Class B extends Thread{
Socket socket;
public void setSocket(Socket p_socket) throws IOException
{
if(socket!=null && !socket.isClosed())
{
try{
socket.close();
socket = null;
Thread.sleep(5);
}
catch(Exception ex)
{}
}
socket = p_socket;
inputStream = socket.getInputStream(); // Here I am getting socket.closed() exception very much.
}
This worked fairly good in the past but now recently I am very very frequently getting the following error.
java.io.IOException: Socket Closed
at java.net.AbstractPlainSocketImpl.getInputStream(AbstractPlainSocketImpl.java:421)
at java.net.Socket$2.run(Socket.java:914)
at java.net.Socket$2.run(Socket.java:912)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.Socket.getInputStream(Socket.java:911)
I don't understand why this is happening now after years of working fine. Is this due to the network problem or Thread related something?
Updated:
Can this be the server related problem? Because the same application is running on other server but they are not having this problem.
The whole setup concept looks a bit broken. You should not "change" resources from the outside, while maybe there is still some work going on in that thread. A way better concept is to encapsulate the Socket into a new worker thread:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class WrapHandler {
static public class Server {
private final ServerSocket mSocket;
private final ArrayList<Handler> mRunningHandlers = new ArrayList<>();
public Server(final int pPort) throws IOException {
mSocket = new ServerSocket(pPort);
new Thread(() -> mainLoop()).start();
}
private void mainLoop() {
while (true) {
try {
#SuppressWarnings("resource") final Socket socket = mSocket.accept(); // do not close, do not handle with resource, socket will be closed by handler!
final Handler h = new Handler(socket, this);
handlerStarted(h);
} catch (final IOException e) {
e.printStackTrace(); // do something useful
}
}
}
synchronized void handlerStarted(final Handler pHandler) {
mRunningHandlers.add(pHandler);
}
synchronized void handlerEnded(final Handler pHandler) {
mRunningHandlers.remove(pHandler);
}
void handleException(final Handler pHandler, final Throwable pException) {
/* again do something useful */
}
}
static public class Handler {
private final Socket mSocket;
private final Server mServer;
public Handler(final Socket pSocket, final Server pServer) {
mSocket = pSocket;
mServer = pServer;
new Thread(() -> handleSocket()).start();
}
private void handleSocket() {
try {
handleData();
} catch (final IOException e) {
mServer.handleException(this, e);
} finally {
mServer.handlerEnded(this);
stop();
}
}
private void handleData() throws IOException {
mSocket.getInputStream().read();
/* data handling code here */
}
void stop() {
try {
mSocket.close();
} catch (final IOException e) { /* ignore or handle as you will */ }
}
}
}
Related
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 6 years ago.
Hi all :) Sorry for this really long question but this needs some explaination.
I was given an assignment where i have to turn a very simple game into a 2 player multiplayer game. The reason why we have to make this game is to learn more about threads and concurrency. I have never worked with concurrency nor with multiple threads.
My idea is to create a TCP server like i have done in GameServer.java where i create a new ServiceObject for each player. I create a thread for each ServiceObject where i will recieve, handle and send commands from a client.
Gameserver.java
package server;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class GameServer {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(6789);
System.out.println("Waiting for clients to connect . . . ");
Socket s1 = server.accept();
System.out.println("Clients connected.");
PlayerService servicep1 = new PlayerService(s1);
Thread t1 = new Thread(servicep1);
Socket s2 = server.accept();
System.out.println("Clients connected.");
PlayerService servicep2 = new PlayerService(s2);
Thread t2 = new Thread(servicep2);
t1.start();
t2.start();
servicep1.sendDataToClient("ready");
servicep2.sendDataToClient("ready");
}
}
PlayerService.java
package server;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.concurrent.LinkedBlockingQueue;
import game2016.Player;
public class PlayerService extends Thread {
private Socket s;
private PlayerService opponent;
private Scanner in;
private PrintWriter out;
public PlayerService(Socket aSocket) {
this.s = aSocket;
}
public void setOpponent(PlayerService opponent) {
this.opponent = opponent;
}
public void run() {
try {
in = new Scanner(s.getInputStream());
out = new PrintWriter(s.getOutputStream());
try {
doService();
} finally {
// s.close();
}
} catch (IOException exception) {
exception.printStackTrace();
}
}
public void doService() throws IOException {
while (true) {
if (!in.hasNext()) {
return;
}
String command = in.next();
if (command.equals("QUIT")) {
return;
} else
recieveFromClient(command);
}
}
public void recieveFromClient(String command) throws IOException {
System.out.println(command);
if(command.equals("player")) {
String newPlayerName = in.next();
int xPos = in.nextInt();
int yPos = in.nextInt();
String direction = in.next();
// sendDataToOpponent("addOpponent " + newPlayerName + " " + xPos + " " + yPos + " " + direction);
}
}
public void sendDataToClient(String response) {
out.write(response + "\n");
out.flush();
}
public void sendDataToOpponent(String response) {
opponent.sendDataToClient(response);
}
}
To send data from one client to another client i have a reference to the opponents servicelayer as i can invoke the sendDataToOpponent() method to send data to him and if the server have to communicate i can just invoke sendDataToClient() from the server.
My problem is that i want to postpone opening my clients GUI to both clients have connected.
Main.java(Client) - GUI code have been left out
private static Socket s;
private static InputStream instream;
private static OutputStream outstream;
private static Scanner in;
private static PrintWriter out;
private static boolean isOpponentConnected;
public static void main(String[] args) throws Exception {
openConnection();
reciever();
waitOpponentConected();
launch(args);
}
public static void waitOpponentConected() throws Exception {
while(!isOpponentConnected) {
System.out.println("Waiting for opponent");
Thread.sleep(2000);
}
System.out.println("Opponent is ready now");
}
public static void openConnection() throws IOException {
s = new Socket("localhost", 6789);
System.out.println("Connection established");
instream = s.getInputStream();
outstream = s.getOutputStream();
in = new Scanner(instream);
out = new PrintWriter(outstream);
}
public static void responseFromServer() throws IOException {
try {
while(in.hasNext()) {
String response = in.next();
if(response.equals("ready")) {
isOpponentConnected = true;
System.out.println("Ready");
}
}
} catch (Exception e) {
}
}
public static void reciever() {
Task<Void> task = new Task<Void>() {
#Override
protected Void call() throws Exception {
while(true) {
responseFromServer();
}
}
};
new Thread(task).start();
}
public static void sendCommandToServer(String command) throws IOException {
out.print(command + "\n");
out.flush();
}
I've created a Thread to recieve commands from the server, and when both clients have connected to the server it sends a string 'ready' to each of the clients. My thought was that The Main-thread sleeps till isOpponentConnected is true.
But my gameserver fails and prints out a nullpointer exception when the second clients connects to the server. I've spend to days reading and trying to fix this bug. When i run the code in debug mode, both clients recieves the ready signal and the GUI starts for both clients.
Exception in thread "main" java.lang.NullPointerException
at server.PlayerService.sendDataToClient(PlayerService.java:67)
at server.GameServer.main(GameServer.java:23)
Can you guys see anything i'm obviously doing wrong?
I think this queston is interesseting because it's not just the nullpointerexception, it's about structering TCP server-client relationships and the chain when things are initialized and ready when threads and connections are made.
It should be fixable from inside the PlayerService.java class you have posted.
I suggest moving:
in = new Scanner(s.getInputStream());
out = new PrintWriter(s.getOutputStream());
from public void run() to your PlayerService constructor:public PlayerService(Socket aSocket)
It looks like the function sendDataToClient is trying to use the out variable before it gets initialised.
I have a class that implements Runnable, and I start it's own thread in another method that runs when the window opens, however the while loop I have in the Runnable method only runs once, I know this because it displays the output only once. This is the code below.
static private final int SOCKET = 2222;
static JFrame frame = new JFrame();
static private ServerSocket serverSocket;
static private Socket socket;
static private DataOutputStream out;
static private DataInputStream in;
static private ArrayList<User> users = new ArrayList<>();
static private int logged = -1;
public GameServer() {
initComponents();
}
public void runServer() {
Thread server = new Thread(new StartServer());
server.start();
}
public void addUser(int logged, Socket socket, JTextArea taOut) {
users.add(logged, new User(socket, taOut, this, logged));
Thread thread = new Thread(users.get(logged));
thread.start();
}
public void removeUser(int index, Socket socket) {
users.remove(index);
updateIndexes();
try {
socket.close();
} catch (Exception e) {
taOut.append("Failed to close connection to user.\n");
}
}
public void updateIndexes() {
for (int i = 0; i == users.size()+1; i++) users.get(i).lowerIndex();
logged--;
}
public class StartServer implements Runnable {
#Override
public void run() {
taOut.append("Attempting to start server.\n");
try {
serverSocket = new ServerSocket(SOCKET);
} catch (Exception e) {
taOut.append("Port "+SOCKET+" is in use.\n");
return; // Prevent any further code from executing
}
taOut.append("Server started successfully.\n");
while (true) {
try {
taOut.append("Waiting for user...\n");
socket = serverSocket.accept(); // Wait for user to connect
logged++;
addUser(logged, socket, taOut);
taOut.append("Login request from: "+socket.getInetAddress()+"\n");
} catch (Exception e) {
taOut.append("There was an error with a user trying to connect.\n");
}
break;
}
}
}
private void formWindowOpened(java.awt.event.WindowEvent evt) {
runServer();
}
The body of the loop ends with a break; that terminates the loop. Just remove it and you should be fine.
This question already has answers here:
Java socket API: How to tell if a connection has been closed?
(9 answers)
Closed 7 years ago.
i am trying to make a chat program. The problem i am having is that my loop in the EchoThread always thinks that the connection is true. I have tried to use if(s.isConnected() == false) but that didn't work also i tried to do if(s.isClosed() == true) if you can help thank you in advance. Here is my code
import java.io.*;
import java.net.*;
import java.util.ArrayList;
public class server {
public ObjectInputStream input;
public ServerSocket server;
public Socket s;
public ObjectOutputStream output;
public ArrayList<ObjectOutputStream> outputs = new ArrayList<ObjectOutputStream>();
public ArrayList<Socket> users = new ArrayList<Socket>();
public class Accept implements Runnable {
public void run() {
try {
server = new ServerSocket(55555, 100);
} catch (IOException e) {
e.printStackTrace();
}
while(true) {
try {
s = server.accept();
new EchoThread(s).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public class EchoThread extends Thread {
private Socket s1;
public EchoThread(Socket s) throws IOException {
this.s1 = s;
}
public void run() {
users.add(s1);
try {
outputs.add(new ObjectOutputStream(s1.getOutputStream()));
newUser();
} catch (IOException e) {
System.out.println("Error 2");
}
while(s1.isConnected() == true) {
// loops until socket looses connection
}
System.out.println("Disconnected");
}
}
public class check implements Runnable {
public void run() {
}
}
public void newUser() {
try {
for(ObjectOutputStream o: outputs) {
o.writeObject(s.getInetAddress() + " Connected");
}
} catch (IOException e1) {
System.out.println("Error 21");
}
}
server() throws IOException {
Thread t = new Thread(new Accept());
t.start();
Thread ch = new Thread(new check());
ch.start();
}
public static void main(String[] args) throws IOException {
new server();
}
}
you have to read this, you have to check with the read()method to check if it returns -1.
https://stackoverflow.com/a/10241044/964152
while(s1.isConnected() == true) {
This is not a valid loop. isConnected() is true because you accepted the socket, and it doesn't magically become false afterwards. When the client disconnects, you will get the appropriate end of stream indication from whichever read method you're calling.
I am using RXTX to communicate between JAVA and a microcontroller.
This is the JAVA code for opening a connection, sending and receiving data
package app;
import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class SerialCommunication1 {
private static SerialCommunication1 instance = null;
private static boolean coonected = false;
public static SerialCommunication1 getInstance(){
if(instance == null)
instance = new SerialCommunication1();
return instance;
}
private SerialCommunication1() {
super();
try {
connect("COM4");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
SerialCommunication1.coonected = true;
}
void connect(String portName) throws Exception {
CommPortIdentifier portIdentifier = CommPortIdentifier
.getPortIdentifier(portName);
if (portIdentifier.isCurrentlyOwned()) {
System.out.println("Error: Port is currently in use");
} else {
CommPort commPort = portIdentifier.open(this.getClass().getName(),
2000);
if (commPort instanceof SerialPort) {
SerialPort serialPort = (SerialPort) commPort;
serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8,
SerialPort.STOPBITS_2, SerialPort.PARITY_NONE);
InputStream in = serialPort.getInputStream();
OutputStream out = serialPort.getOutputStream();
(new Thread(new SerialReader(in))).start();
(new Thread(new SerialWriter(out))).start();
} else {
System.out
.println("Error: Only serial ports are handled by this example.");
}
}
}
/** */
public static class SerialReader implements Runnable {
InputStream in;
public SerialReader(InputStream in) {
this.in = in;
}
public void run() {
byte[] buffer = new byte[1024];
int len = -1;
try {
while ((len = this.in.read(buffer)) > -1) {
System.out.print(new String(buffer, 0, len));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/** */
public static class SerialWriter implements Runnable {
OutputStream out;
static String str = null;
public SerialWriter(OutputStream out) {
this.out = out;
}
public void run() {
System.out.println("Will try to execute");
try {
if(str.length() > 0){
this.out.write(str.getBytes());
str = null;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
And this is the Java code that is calling when an event triggers
SerialCommunication1.getInstance();
if(ledStatus == true) {SerialCommunication1.SerialWriter.str = "4A01";}
else {SerialCommunication1.SerialWriter.str = "4A00";}
stopProcess();
And now the problem. I need to send a command to my microcontroller with the code 4A01 and, after receiving the answer, I need to call it again with the code 4A00. The calls are triggered by a button from my Java interface. The problem is that the second call is not executed (4A00 is not sending). I tried to inverse the command codes and they work well. After the first one (4A01) is executed, my microcontroller reacts and sends the response which is read by java and my interface is updated. When I send the invers command (4A00) it stops exactly at this line SerialCommunication1.SerialWriter.str = "4A00"; and doesn't even enter inside the SerialWriter's run() method.
Do you have any idea why is this happening? From the side of my microcontroller there is no problem, I checked all the possibilities with a tool.
I hope I made myself clear.
Thank you!
LE: I forgot to tel you that it didn't throw any errors or exceptions
I'm not sure because I'm not able to test your code but I think your problem is in SerialWriter class:
public static class SerialWriter implements Runnable {
OutputStream out;
static String str = null; // Here str is initialized to null
public SerialWriter(OutputStream out) {
this.out = out;
}
public void run() {
System.out.println("Will try to execute");
try {
if(str.length() > 0) { // this should throw NPE because str is null
this.out.write(str.getBytes());
str = null;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Since there is no loop in this method, then the thread created within SerialCommunication1 at this line:
(new Thread(new SerialWriter(out))).start();
most likely finishes its execution after sending the first str.
Honestly I don't understand how does it even send a single string, since str is initialized to null in first place and it should throw NullPointerException at str.length() line.
I would suggest you this approach:
Don't trigger a writer thread when connection is established, just trigger a new one every time a message will be sent.
Use Singleton pattern correctly.
Keep a reference to the serial port in SerialCommunication1 class.
Translated to code it would be something like this:
class SerialWriter implements Runnable {
OutputStream out;
String message;
public SerialWriter(OutputStream out) {
this.out = out;
}
public void setMessage(String msg) {
this.message = msg;
}
public void run() {
try {
if(message != null) {
this.out.write(str.getBytes());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Then in SerialCommunication1 class add this public method:
public void sendMessage(String msg) {
SerialWriter writer = new SerialWriter(serialPort.getOutputStream()); // of course you'll have to keep reference to serialPort when connection is established
writer.setMessage(msg);
(new Thread(writer)).start();
}
And finally call this method in this way:
SerialCommunication1.getInstance().sendMessage("4A01");
tzortzik,
I think tha is a timeout problem. Try to addding a delay to writer :
/** */
public static class SerialWriter implements Runnable {
OutputStream out;
static String str = null;
public SerialWriter(OutputStream out) {
this.out = out;
}
public void run() {
Thread.sleep(500); //<----------- this should be in mainThread before to SerialWriter.start();
System.out.println("Will try to execute");
try {
if(str.length() > 0){
this.out.write(str.getBytes());
str = null;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
It happens to me many times, "we should learn to wait for a response" (^_^)
Check if you are executing well a secuence like the next:
Send command 4A01
Receive response 4A01 from micro
WAIT FOR RESPONSE BEFORE SEND SECOND COMMAND. Thread.sleep(500); //wait for 500 milis or more
Send command 4A00
Receive response 4A00 from micro
I hope it could help you.
class SomeUI
{
SocketMessageSender messageSender;
// ensure that its initialized ...
private void bSendMessageActionPerformed(java.awt.event.ActionEvent evt) {
try {
// TODO add your handling code here:
messageSender.sendMessage(jMessage.getText());
jMessage.setText("");
} catch (IOException ex) {
Logger.getLogger(TeKServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
ERROR: Exception in thread "AWT-EventQueue-0" java.lang.RuntimeException: Uncompilable source code - Erroneous sym type: bSendMessageActionPerformed
Why do you keep opening the socket and closing it on every button click. Create a class that allow you to keep the socket open for as long as your application run. The socket connection can be done when the application starts.You can try out the following class
public class SocketMessageSender
{
private String host;
private int port;
private DataOutputStream dos;
public SocketMessageSender(String host, int port)
{
this.host = host;
this.port = port;
}
// call when application starts
public void initConnection() throws IOException
{
InetAddress address = InetAddress.getByName(host);
Socket connection = new Socket(address, port);
dos = new DataOutputStream(connection.getOutputStream());
}
//call from button click
public void sendMessage(String message) throws IOException
{
if(dos != null)
{
dos.writeUTF(message);
dos.flush();
}
}
// call when application exits
public void closeConnection() throws IOException
{
if(dos!= null)
{
dos.close();
}
}
}
Hope it helps ...
Assume you have a class like
class SomeUI
{
SocketMessageSender messageSender;
// ensure that its initialized ...
private void bSendMessageActionPerformed(java.awt.event.ActionEvent evt) {
messageSender.sendMessage(jMessage.getText());
jMessage.setText("");
}
}
I think that the class signature should be something like this ....
public class MyPanel extends JPanel implements ActionListener
{
private SocketMessageSender messageSender;
private Message jMessage = new Message();// This is just a temp class, replace this with your class
public MyPanel()
{
messageSender = new SocketMessageSender("some host", 8080);
try
{
messageSender.initConnection();
}
catch(IOException e)
{
Logger.getLogger(MyPanel.class.getName()).log(Level.SEVERE, null, e);
}
}
#Override
public void actionPerformed(ActionEvent e)
{
try {
// TODO add your handling code here:
messageSender.sendMessage(jMessage.getText());
jMessage.setText("");
} catch (IOException ex) {
Logger.getLogger(MyPanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Consider using ObjectOutputStream/ObjectInputStream and write object through sockets.
There are a lot of examples at java2s.com
Please mind that if you are writing same object multiple times, you will need to reset() stream before writing, and flush after it.