My program is set & ready, the problem is within the server. When I clients send the message, where should it be stored at ? I tried using queue but didn't work, also tried to use a usual string register but it worked partially. I made a thread for the sending & a thread for storing, using "Read/write UTF". I would be more than grateful if somebody provided me with an algorithm , or at a least a better idea. Code :
class clientThread extends Thread {
DataInputStream fromClient;
int counter = 0;
public clientThread(Socket cs) throws IOException
{
fromClient = new DataInputStream(cs.getInputStream());
}
public void run()
{
while (true)
{
try {
toall=Integer.toString(counter)+fromClient.readUTF();
} catch (IOException ex) {
Logger.getLogger(ChatTerminalS.class.getName()).log(Level.SEVERE, null, ex);
}
counter++;
}
}
}
class SendingThread extends Thread
{
DataOutputStream toClient;
String s = "";int counter=0;
public SendingThread(Socket cs) throws IOException
{
toClient = new DataOutputStream(cs.getOutputStream());
}
public void run()
{
while (true)
{
if(toall.charAt(0)+""==Integer.toString(counter))
{}
else
{
try {
toClient.writeUTF(toall);
} catch (IOException ex) {
Logger.getLogger(ChatTerminalS.class.getName()).log(Level.SEVERE, null, ex);
}
counter++;
}
}
}
Related
I tried finding a question that covered my problem, but all I could find were lots of similar questions, but no answer that solved my problem.
I am creating a java webapp for Tomcat, that, between other things, must also act as a TCP server that handles multiple incoming connections: to do so, I run the TCP server code in a separate thread, which in turn uses a ExecutorService to create threads for each connection. The problem basically is that, when I stop Tomcat, the server thread never gets stopped (even if no one has connected yet) and hangs Tomcat, until I close the related process in the Task Manager.
So, this is the starting point of the program:
private TCPServer tcpServer;
Thread serverThread;
#Override
public void init() throws ServletException {
DBConn = getDBConn();
if (DBConn != null) {
//initiates loggers, reads configurations from a file, etc
//starts TCP server
tcpServer = new TCPServer(50001, 200);
serverThread = new Thread(tcpServer);
serverThread.start();
//will be doing other stuff
} else {
//handles DB connection failure
}
}
This is the TCPServer class:
public class TCPServer implements Runnable {
private final int listeningPort;
PrintWriter out;
BufferedReader in;
ServerSocket serverSocket;
private final ExecutorService pool;
public TCPServer(int port, int poolSize) {
listeningPort = port;
pool = Executors.newFixedThreadPool(poolSize);
}
#Override
public void run() {
LinkedBlockingQueue<Socket> queue = new LinkedBlockingQueue<>();
try {
serverSocket = new ServerSocket(listeningPort);
while (!Thread.currentThread().isInterrupted()) {
pool.execute(new ConnectionHandler(queue));
queue.put(serverSocket.accept());
}
} catch (IOException | InterruptedException ex) {
Logger.getLogger(TCPServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
private class ConnectionHandler implements Runnable {
private LinkedBlockingQueue<Socket> socketQueue;
public ConnectionHandler(LinkedBlockingQueue<Socket> queue) {
this.socketQueue = queue;
}
#Override
public void run() {
while (!Thread.interrupted() || !Thread.currentThread().isInterrupted()) {
try (Socket clientSocket = socketQueue.take()) {
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String line = in.readLine();
System.out.println("Incoming: " + line);
clientSocket.close();
} catch (InterruptedException ex) {
Logger.getLogger(TCPServer.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(TCPServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public void close(){
Thread.currentThread().interrupt();
try {
serverSocket.close();
} catch (IOException ex) {
Logger.getLogger(TCPServer.class.getName()).log(Level.SEVERE, null, ex); }
pool.shutdownNow();
}
}
I added, in the main class (the same where the init() above is), this override, that runs when Tomcat gets closed:
#Override
public void contextDestroyed(ServletContextEvent sce) {
serverThread.interrupt();
tcpServer.close();
ServletContextListener.super.contextDestroyed(sce);
}
I made so many edits trying to implement solutions that I found around on the internet, that surely some of this code is probably redundant or useless.
Can someone give me pointers on what I should do to correctly stop the TCPServer thread?
Thanks to this answer and Kayaman's comment, I revised the whole code and somehow got it working.
The init() override is the same, while the contextDestroyed override now is
#Override
public void contextDestroyed(ServletContextEvent sce) {
tcpServer.close();
serverThread.interrupt();
ServletContextListener.super.contextDestroyed(sce);
}
The TCPServer class now is:
public class TCPServer implements Runnable {
private final int listeningPort;
PrintWriter out;
BufferedReader in;
ServerSocket serverSocket;
private final ExecutorService pool;
public TCPServer(int port, int poolSize) {
listeningPort = port;
pool = Executors.newFixedThreadPool(poolSize);
}
#Override
public void run() {
try {
serverSocket = new ServerSocket(listeningPort);
while (!Thread.currentThread().isInterrupted()) {
Socket clientSocket = serverSocket.accept();
pool.submit(new ConnectionHandler(clientSocket));
}
} catch (IOException ex) {
Logger.getLogger(TCPServer.class.getName()).log(Level.SEVERE, null, ex);
} finally {
pool.shutdown();
}
}
private class ConnectionHandler implements Runnable {
private Socket sock;
public ConnectionHandler(Socket sock){
this.sock = sock;
}
#Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try{
in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
String line = in.readLine();
System.out.println("Incoming: " + line);
sock.close();
} catch (IOException ex) {
Logger.getLogger(TCPServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
public void close(){
try {
serverSocket.close();
} catch (IOException ex) {
Logger.getLogger(TCPServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
I'm making Chatting-Room program using the Java Swing.
In the client side, I was saw that doesn't read message from the server side.
The writeUTF() method of the client side is very well and I'm checked readUTF and writeUTF on the server side, that was very well too.
I think the problem is code which does as "Receiver" on the client side.
In the run() method of Thread, The instance dis of the DataInputStream has continuously null value.
I'm so confusing.. Please give me some help.
The bellow is part of my client&server code.
Thanks!
Client code
RoomBackground.java
public class RoomBackground {
private static String socket_server = "127.0.0.1";
private static Socket chatSocket;
private static DataOutputStream dos;
private static DataInputStream dis;
private ChatReceiver chatReceiver;
public Socket getChatSocket() {
return chatSocket;
}
public static DataOutputStream getDos() {
return dos;
}
public RoomBackground() throws IOException {
chatSocket = new Socket(socket_server, 7777);
chatReceiver = new ChatReceiver();
chatReceiver.start();
dos = new DataOutputStream(chatSocket.getOutputStream());
dis = new DataInputStream(chatSocket.getInputStream());
dos.writeUTF(User.getUser().getUsername());
dos.flush();
}
class ChatReceiver extends Thread {
#Override
public void run(){
try {
# PROBLEM CODE..... Allways "dis is null"
System.out.println("dis is " + dis);
# This line never executed.
while(dis != null) {
# some codes.....
}
} catch (IOException e) {
e.printStackTrace();
System.out.println(e.toString());
} catch (BadLocationException e) {
e.printStackTrace();
}
}
}
}
RoomFrame.java
public class RoomFrame extends JFrame{
private RoomBackground roomBackground;
public RoomFrame(int roomId) throws IOException {
chatField.addActionListener(new ActionListener() {
roomBackground = new RoomBackground();
#Override
public void actionPerformed(ActionEvent e) {
String msg = chatField.getText() + "\n";
try {
RoomBackground.getDos().writeUTF(msg);
# It works.
System.out.println("sent msg is " + msg);
} catch (IOException e1) {
e1.printStackTrace();
}
chatField.setText("");
}
});
}
}
Now server code.
Server Background.java
public class ChatReceiver extends Thread {
private DataInputStream in;
private DataOutputStream out;
public ChatReceiver(Socket chatSocket) throws IOException {
out = new DataOutputStream(chatSocket.getOutputStream());
in = new DataInputStream(chatSocket.getInputStream());
nick = in.readUTF();
addChatClient(nick, out);
}
#Override
public void run() {
try {
while(in!=null) {
chatMsg = in.readUTF();
# It works !
System.out.println("before send" + chatMsg);
sendMsg(chatMsg);
# It works too!
System.out.println("after send" + chatMsg);
}
}catch (IOException e) {
removeChatClient(nick);
}
}
}
When you are starting the ChatReceiver thread in the RoomBackground the dis object is not initialized yet, that is why it is null. One solution could be to initialize the dis variable in the ChatReceiver constructor.
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.
I have a a GPS receptor. I create a class to retrieve all the GPS data on my Eclipse Console.
(This is the code of makia42)
public class COM implements Runnable{
static Thread myThread=null;
static BufferedReader br;
static BufferedWriter wr;
static InputStreamReader isr;
static OutputStreamWriter osw;
static java.io.RandomAccessFile port;
public COM(){ /**Constructeur*/
myThread=new Thread(this);
}
public void start(){
try {
port=new java.io.RandomAccessFile("COM3","rwd");
port.writeBytes("\r\n");
port.writeBytes("c,31,0,0,5\r\n");
port.writeBytes("T,1000,1\r\n");
}
catch (Exception e) {
System.out.println("start "+e.toString());
}
myThread.start();
}
public void run() {
System.out.println("lecture COM...");
for(;;){
String st = null;
try {
st=port.readLine();
} catch (IOException e) {System.out.println(e.getMessage());}
System.out.println(st);
}
}
public static void main(String[] args) {
COM temp= new COM();
temp.start();
}
}
I have another class which is a frame containing a button and a JTextArea. This class is in communication with my first class COM.
When i click the button, COM is starting and show me the data in my Eclipse Console.
But now, I'd like to show it on my JTextArea.
How can I do it ?
Best regards,
Tofuw
Take a moment to read about this pattern.
Make the Thread a Subject. Before starting register the instance of the class that contains the JTextArea as the Observer with the instance of the Thread. At the run() instead of printing on the console, use the notify(String);
public void run() {
System.out.println("lecture COM...");
for(;;){
String st = null;
try {
st=port.readLine();
} catch (IOException e) {System.out.println(e.getMessage());}
System.out.println(st);
}
}
Change to
public void run() {
System.out.println("lecture COM...");
for(;;){
String st = null;
try {
st=port.readLine();
} catch (IOException e) {System.out.println(e.getMessage());}
notifyObservers(st); //Pass the data to the observers.
}
}
EDIT:
I suppose you can rewrite the Thread to a simple class. It will render the program unresponsive while it reads, that's why you have a Thread. I suppose you can implement a cleaner way using Future<String>
public class GpsReader {
public class GenericGPSException extends Exception {
public GenericGPSException(String message, Throwable cause) {
super(message, cause);
}
}
public static void main(String[] args) {
// Example of usage
GpsReader gpsReader = new GpsReader();
String messageFromDevice;
try {
// Try read it
messageFromDevice = gpsReader.getCoordinate();
} catch (GenericGPSException e) {
// Error, what does it says?
messageFromDevice = e.getMessage();
}
JTextArea mockArea = new JTextArea();
// Show to user anything that comes to it.
mockArea.setText(messageFromDevice);
}
private boolean isReady;
private RandomAccessFile port;
public GpsReader() {
}
public String getCoordinate() throws GenericGPSException {
if (!isReady) {
try {
port = new RandomAccessFile("COM3", "rwd");
port.writeBytes("\r\n");
port.writeBytes("c,31,0,0,5\r\n");
port.writeBytes("T,1000,1\r\n");
isReady = true;
} catch (FileNotFoundException e) {
throw new GenericGPSException(
"Error at starting communication to Device ", e);
} catch (IOException e) {
throw new GenericGPSException(
"Error at starting communication to Device ", e);
}
}
try {
return port.readLine();
} catch (IOException e) {
throw new GenericGPSException("Error at reading the Device ", e);
}
}
}
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.