Java Networking Server, protocol and client - java

I have this multi server thread, so whenever the 'X' button is click on the top right hand corner, i want to display the message "closing the socket" on the server side.
public void run
{
try
{
// .....
String inputLine, outputLine;
Protocol p = new Protocol();
outputLine = p.processInput(null, p);
out.println(outputLine);
while ((inputLine = in.readLine()) != null) {
outputLine = p.processInput(inputLine,p);
out.println(outputLine);
if (outputLine.equals("Bye"))
{
System.out.print("Closing socket.");
break;
}
}
out.close();
in.close();
socket.close();
catch (IOException e)
{
// .....
}
}
public String processInput(String theInput, Protocol p)
{
theOutput = null;
frame = new JFrame ("Find The Word!");
frame.addWindowListener( new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
theOutput = "Bye";
}
});
frame.add(p);
frame.pack();
frame.setVisible(true);
return theOutput;
}
But it doesn't work, and i have to manually end the process for the server side. I assume that it got stuck at the while loop, but i couldn't figure out whats wrong with it.

Assuming you can't induce the server to send you a Bye messages, you can drop out of the loop as if it had sent you a Bye message or close the socket from another thread.

Related

Java Multiple threads using a client socket

I'm creating a server based chat program that has multiple worker threads each handling a client on a socket. It has a single server socket that passes off the client to the worker thread.
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(4001);
System.out.println("Listening server");
while (true) {
Socket socket = serverSocket.accept();
System.out.println("Connected");
Random rand= new Random();
int port=4001+rand.nextInt(5);
Worker worker = new Worker(port);
executor.execute(worker);
System.out.println("Thread started");
new PrintWriter(socket.getOutputStream(), true).println(port);
socket.close();
System.out.println("Closed");
// break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
public class Worker implements Runnable {
private int port;
public Worker(int i) {
port=i;
}
#Override
public void run() {
worker();
}
private static Socket socket;
private static PrintWriter out;
private static BufferedReader in;
private void worker() {
try {
ServerSocket serverSocket = new ServerSocket(port);
socket = serverSocket.accept();
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
System.out.println("Received: " + line);
switch (line) {
case ("Button Press"):
System.out.println("Handled button");
out.println("Button acknowledged");
break;
case ("Give me some data"):
System.out.println("Handled data");
out.println("Have some data");
break;
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
out.close();
in.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
This works fine, however the issue is when I have an automated request by the client to check for messages and the user provides some input at the same type. This causes conflict as the actual methods take a couple of seconds to run and if more input is received then the request won't be handled because its in the middle of the method. For example:
private static BufferedReader in;
private static PrintWriter out;
public static void main(String[] args) {
Main main=new Main();
main.createWindow();
try {
Socket init = new Socket(InetAddress.getLocalHost(), 4001);
int port
=Integer.parseInt
(new BufferedReader
(new InputStreamReader(init.getInputStream())).readLine());
init.close();
Socket socket=new Socket(InetAddress.getLocalHost(), port);
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while(true){
try {
Thread.sleep(5000);
out.println("Give me some data");
if(in.readLine().equals("Have some data")){
System.out.println("Data recieved");
}else{
System.out.println("Data not recieved");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void createWindow(){
JFrame frame =new JFrame("This is a button");
Container pane=getContentPane();
JButton button=new JButton("This is a button");
button.addActionListener(this);
pane.add(button);
frame.setTitle("Messaging");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(pane);
frame.setVisible(true);
frame.setSize(400, 350);
}
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Button press");
try {
out.println("Button Press");
if(in.readLine().equals("Button acknowledged")){
System.out.println("Button complete");
}else{
System.out.println("Button fail");
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
If the button is pressed whilst the server is fetching data it conflicts and the wrong response is sent. So how would I deal with this? If I create a separate socket to just handle automated checks that's double the amount of threads the server has to cope with. Is there a better solution?
And please can you try to explain as this is a new area for me.
Your problem is that you have two threads interacting with the socket, your main thread and the Swing event handling thread. This means that the two threads can queue two different things, and the responses may be picked up by the wrong thread. The simplest way to get where you want to be is to put all the socket interaction in one thread.
There are two ways to do this. One would be for the main thread to queue the periodic automated checks to the Swing event handling thread. However, that's a bit complicated and also possibly buggy as the actual Swing threading model is different from what's documented.
The other way to do it would be for the Swing event handling thread to queue button presses to the main thread. In this case, you would queue the button press to the main thread using proper synchronization. The main loop of the main thread would check for button presses and send them through the socket and wait for the proper response.

Server is not able to receive the text from client java

I am creating an app in which client can send some text to server on button click.I want to print that text on console server side,but whenever client side button is pressed nothing happens.
and after sometimes i got this line on console android.support.v7.widget.AppCompatEditText#b2253390.
I am not getting why this is happening ?
SERVER CODE :
public static ServerSocket server = null;
public static Socket client = null;
public static void main(String []arg)throws IOException{
try {
server = new ServerSocket(8002);
System.out.println("Server Started...............");
while(true){
client = server.accept();
DataInputStream in = new DataInputStream(client.getInputStream());
String msg = in.readLine();
System.out.println("and: "+msg);
}
}catch(IOException r){
System.out.println("error :"+r.getMessage());
}
}
CLIENT CODE:
public void send(){
send.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
Socket cs = null;
try {
cs = new Socket("192.168.1.100", 8002);
DataOutputStream out = new DataOutputStream(cs.getOutputStream());
out.writeBytes(text.toString());
} catch (IOException e) {
Toast.makeText(KeyboardActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}
);
}
It is because text is an EditText.
I think you actually meant,
out.writeBytes(text.getText().toString());
Instead of,
out.writeBytes(text.toString());

JScrollPanel is not responding initially

I wanted to make a chat server client with GUI. Any new messages will be added as a JPanel. Initially messages added to my JScrollPanel is updating smoothly. However when i implemented the server and client to work with the GUI, the first few new messages added are never updated. Messages will only be updated to the JScrollPanel after the third add onward. Some times the adding of components ended prematurely. The client implements runnable so any new messages will be updated to the JScrollPanel via a Thread.
It seems like the GUI did not fully initialise.
this is the Client code
public static void main(String[] args) {
new Thread(new MessageClient("htf0001")).start();
MessageGUI dialog = new MessageGUI(collaID);
}
#Override
public void run() {
//loop read from server
// The default port.
int portNumber = 50000;
// The default host.
String host = "localhost";//"54.169.62.79";
/*
* Open a socket on a given host and port. Open input and output streams.
*/
try {
clientSocket = new Socket(host, portNumber);
oos = new ObjectOutputStream(clientSocket.getOutputStream());
oos.flush();
ois = new ObjectInputStream(clientSocket.getInputStream());
Staff staff = new Staff();
sendToServer(staff.connectToMessageServer(collaID));
sendToServer(staff.getMessageLog(collaID));
while(!close){
ArrayList<String> input = new ArrayList<String>();
Object o = ois.readObject();
input = (ArrayList<String>) o;
if(input.get(0).compareTo("end")!=0){
for(int i=0;i<input.size();i=i+5){
MessageGUI.addMessage(input.get(i),input.get(i+1), input.get(i+2),
input.get(i+3),input.get(i+4));
}
}
else close = true;
}
oos.close();
ois.close();
clientSocket.close();
}
catch (UnknownHostException uhe) {
JOptionPane.showMessageDialog(null,uhe.getMessage());
}
catch (IOException ioe) {
JOptionPane.showMessageDialog(null,ioe.getMessage());
}
catch (ClassNotFoundException ex) {
JOptionPane.showMessageDialog(null,ex.getMessage());
}
}
this is the GUI code part that add in the component
public static void addMessage(String date, String firstName, String lastName,
String message, String time){
String newUser = firstName + " " + lastName;
if(recentDate.compareTo(date)!=0){
JLabel newDate = new JLabel(date);
newDate.setHorizontalAlignment(SwingConstants.CENTER);
addComponent(newDate,nextLine,0,3,1);
recentDate = date;
nextLine++;
}
if(recentUser.compareTo(newUser)==0 && recentTime.compareTo(time)==0){
recentJTextArea.append("\n\n"+message);
}
else{
if(recentUser.compareTo(newUser)==0) newUser = recentUser;
JTextArea temp = new JTextArea();
temp.setFocusable(false);
temp.setBorder(BorderFactory.createTitledBorder(newUser));
temp.setLineWrap(true);
temp.setWrapStyleWord(true);
temp.setEditable(false);
temp.setText(message);
recentJTextArea = temp;
recentUser = newUser;
JLabel newTime = new JLabel(time);
newTime.setHorizontalAlignment(SwingConstants.RIGHT);
recentTime = time;
addComponent(temp,nextLine,0,2,1);
nextLine = nextLine + 1;
addComponent(newTime,nextLine,1,1,1);
nextLine = nextLine + 1;
}
invokeLater(new Runnable() {
public void run() {
ChatLogJScrollPane.getVerticalScrollBar().setValue(ChatLogJScrollPane.getVerticalScrollBar().getMaximum());
}
});
}
Seems like you are updating (ie adding the chat text) to your text areas on a thread that is not the GUI thread. Instead, you should call
SwingUtilities.invokeLater(new Runnable() {
temp.setText(message);
temp.repaint();
});
I've found the solution. I need to validate the JPanel in my JScrollPanel.
JPanel container
JScrollPanel(container)
SwingUtilities.invokeLater(new Runnable(){
container.validate();
});

Java SWT updating canvas from another thread

I'm developing a Java application that does basically:
Starts a server in a new thread. This server opens a socket connection and waits for messages.
Creates a Shell with a Canvas (in the main thread) and whenever server receives a message, I need to draw a line using the points contained in it.
I've already read some threads about this issue (on updating SWT from another thread) and I've tried to create a method called by my server whenever it receives a message:
public static void doPaint(final Canvas canvas, final Draw draw){
if (canvas != null && draw != null){
Display.getDefault().syncExec(new Runnable() {
#Override
public void run() {
canvas.addPaintListener(new PaintListener() {
#Override
public void paintControl(PaintEvent e) {
System.out.println("Printing line....");
e.gc.setBackground(e.display.getSystemColor(SWT.COLOR_WHITE));
e.gc.setForeground(e.display.getSystemColor(SWT.COLOR_BLACK));
e.gc.setLineWidth(3);
e.gc.drawLine((int)draw.getStartX(),(int)draw.getEndX(),(int)draw.getStartY(),(int)draw.getEndY());
}
});
}
});
}
}
EDIT
This is the loop that waits for socket messages and triggers the actions:
while(isConnected()){
try{
System.out.println("Waiting for connection...");
Socket server = getServerSocket().accept();
BufferedReader in = new BufferedReader(new InputStreamReader(server.getInputStream(), Const.ENC_UTF8));
String inputLine;
while(((inputLine = in.readLine()) != null)){
processInput(inputLine, canvas);
}
}catch(IOException ioex){
System.out.println(ioex.getMessage());
ioex.printStackTrace();
}catch (Exception ex) {
System.out.println(ex.getMessage());
ex.printStackTrace();
}
}
and my processInput method is:
protected void processInput(String inputLine, Canvas canvas){
//get draw from input stream
Draw draw = DrawUtil.getDrawFromInput(inputLine);
//draw points on live-mode
BBCanvas.doPaint(canvas, draw);
//append draw node to XML file
DrawUtil.writeDrawToFile(draw);
}
... but the runnable in the doPaint method is never executed. Any hints?
EDIT 2
This is the code that creates the main shell:
public MainWindow(BBServer server) {
this.server = server;
Display display = new Display();
this.mainShell = createShell(display);
getMainShell().open();
while (!getMainShell().isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}

Server and Client using Sockets

Are there any examples of a server and a client that use sockets, but that have send and get methods? I'm doing this networked battleship program, almost finished, but can't get the server and clients to work. I have made a chat program that only sends strings, but this time I need to send objects. I'm already frustrated, so is there any source code that already has this.
Here's the code for the client... how would you modify it to allow to send objects? Also I need to be listening for incoming objects and process them right away.
import java.net.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SimpleChat extends JFrame {
private Socket communicationSocket = null;
private PrintWriter outStream = null;
private BufferedReader inStream = null;
private Boolean communicationContinue = true;
private String disconnectString = "disconnect764*#$1";
private JMenuItem disconnectItem;
private JTextField displayLabel;
private final Color colorValues[] = { Color.black, Color.blue, Color.red, Color.green };
// set up GUI
public SimpleChat() {
super("Simple Chat");
// set up File menu and its menu items
JMenu fileMenu = new JMenu("File");
fileMenu.setMnemonic('F');
// set up Activate Server menu item
JMenuItem serverItem = new JMenuItem("Activate Server");
serverItem.setMnemonic('S');
fileMenu.add(serverItem);
serverItem.addActionListener(new ActionListener() { // anonymous inner class
// display message dialog when user selects About...
public void actionPerformed(ActionEvent event) {
setUpServer();
}
} // end anonymous inner class
); // end call to addActionListener
// set up Activate Client menu item
JMenuItem clientItem = new JMenuItem("Activate Client");
clientItem.setMnemonic('C');
fileMenu.add(clientItem);
clientItem.addActionListener(new ActionListener() { // anonymous inner class
// display message dialog when user selects About...
public void actionPerformed(ActionEvent event) {
setUpClient();
}
} // end anonymous inner class
); // end call to addActionListener
// set up Activate Client menu item
disconnectItem = new JMenuItem("Disconnect Client/Server");
disconnectItem.setMnemonic('D');
disconnectItem.setEnabled(false);
fileMenu.add(disconnectItem);
disconnectItem.addActionListener(new ActionListener() { // anonymous inner
// class
// display message dialog when user selects About...
public void actionPerformed(ActionEvent event) {
disconnectClientServer(true);
}
} // end anonymous inner class
); // end call to addActionListener
// set up About... menu item
JMenuItem aboutItem = new JMenuItem("About...");
aboutItem.setMnemonic('A');
fileMenu.add(aboutItem);
aboutItem.addActionListener(new ActionListener() { // anonymous inner class
// display message dialog when user selects About...
public void actionPerformed(ActionEvent event) {
JOptionPane.showMessageDialog(SimpleChat.this, "This is an example\nof using menus", "About",
JOptionPane.PLAIN_MESSAGE);
}
} // end anonymous inner class
); // end call to addActionListener
// set up Exit menu item
JMenuItem exitItem = new JMenuItem("Exit");
exitItem.setMnemonic('x');
fileMenu.add(exitItem);
exitItem.addActionListener(new ActionListener() { // anonymous inner class
// terminate application when user clicks exitItem
public void actionPerformed(ActionEvent event) {
disconnectClientServer(true);
System.exit(0);
}
} // end anonymous inner class
); // end call to addActionListener
// create menu bar and attach it to MenuTest window
JMenuBar bar = new JMenuBar();
setJMenuBar(bar);
bar.add(fileMenu);
// set up label to display text
displayLabel = new JTextField("Sample Text", SwingConstants.CENTER);
displayLabel.setForeground(colorValues[0]);
displayLabel.setFont(new Font("Serif", Font.PLAIN, 72));
displayLabel.addActionListener(new ActionListener() { // anonymous inner
// class
// display message dialog when user selects About...
public void actionPerformed(ActionEvent event) {
sendData();
}
} // end anonymous inner class
); // end call to addActionListener
getContentPane().setBackground(Color.CYAN);
getContentPane().add(displayLabel, BorderLayout.CENTER);
setSize(500, 200);
setVisible(true);
} // end constructor
public static void main(String args[]) {
final SimpleChat application = new SimpleChat();
application.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
application.disconnectClientServer(true);
System.exit(0);
}
});
// application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}
public void setCommunicationSocket(Socket sock) {
communicationSocket = sock;
communicationContinue = true;
disconnectItem.setEnabled(true);
}
public void setOutStream(PrintWriter out) {
outStream = out;
}
public void setInStream(BufferedReader in) {
inStream = in;
}
public void setUpServer() {
ServerThread st = new ServerThread(this);
st.start();
}
public void setUpClient() {
ClientThread st = new ClientThread(this);
st.start();
}
public void disconnectClientServer(Boolean sendMessage) {
if (communicationSocket == null)
return;
try {
// shut down socket read loop
communicationContinue = false;
disconnectItem.setEnabled(false);
// send notification to other end of socket
if (sendMessage == true)
outStream.println(disconnectString);
// sleep to let read loop shut down
Thread t = Thread.currentThread();
try {
t.sleep(500);
} catch (InterruptedException ie) {
return;
}
outStream.close();
inStream.close();
communicationSocket.close();
} catch (IOException e) {
System.err.println("Stream Read Failed.");
JOptionPane.showMessageDialog(SimpleChat.this, "Disconnection Failed", "SimpleChat", JOptionPane.PLAIN_MESSAGE);
return;
} finally {
communicationSocket = null;
}
}
public void sendData() {
if (communicationSocket != null) {
String data = displayLabel.getText();
outStream.println(data);
}
}
public void getData() {
String inputLine;
try {
while (communicationContinue == true) {
communicationSocket.setSoTimeout(100);
// System.out.println ("Waiting for Connection");
try {
while (((inputLine = inStream.readLine()) != null)) {
System.out.println("From socket: " + inputLine);
if (inputLine.equals(disconnectString)) {
disconnectClientServer(false);
return;
}
displayLabel.setText(inputLine);
}
} catch (SocketTimeoutException ste) {
// System.out.println ("Timeout Occurred");
}
} // end of while loop
System.out.println("communication is false");
} catch (IOException e) {
System.err.println("Stream Read Failed.");
JOptionPane.showMessageDialog(SimpleChat.this, "Input Stream read failed", "SimpleChat",
JOptionPane.PLAIN_MESSAGE);
return;
}
}
}
class ServerThread extends Thread {
private SimpleChat sc;
private JTextField display;
public ServerThread(SimpleChat scParam) {
sc = scParam;
}
public void run() {
ServerSocket connectionSocket = null;
try {
connectionSocket = new ServerSocket(10007);
} catch (IOException e) {
System.err.println("Could not listen on port: 10007.");
JOptionPane.showMessageDialog(sc, "Could not listen on port: 10007", "Server", JOptionPane.PLAIN_MESSAGE);
return;
}
JOptionPane.showMessageDialog(sc, "Server Socket is now activated", "Server", JOptionPane.PLAIN_MESSAGE);
Socket communicationSocket = null;
try {
communicationSocket = connectionSocket.accept();
} catch (IOException e) {
System.err.println("Accept failed.");
JOptionPane.showMessageDialog(sc, "Accept failed", "Server", JOptionPane.PLAIN_MESSAGE);
return;
}
JOptionPane.showMessageDialog(sc, "Comminucation is now activated", "Server", JOptionPane.PLAIN_MESSAGE);
try {
PrintWriter out = new PrintWriter(communicationSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(communicationSocket.getInputStream()));
sc.setCommunicationSocket(communicationSocket);
sc.setOutStream(out);
sc.setInStream(in);
connectionSocket.close();
sc.getData();
} catch (IOException e) {
System.err.println("Accept failed.");
JOptionPane.showMessageDialog(sc, "Creation of Input//Output Streams failed", "Server", JOptionPane.PLAIN_MESSAGE);
return;
}
}
}
class ClientThread extends Thread {
private SimpleChat sc;
public ClientThread(SimpleChat scParam) {
sc = scParam;
}
public void run() {
Socket echoSocket = null;
PrintWriter out = null;
BufferedReader in = null;
String ipAddress = "127.0.0.1";
try {
echoSocket = new Socket(ipAddress, 10007);
out = new PrintWriter(echoSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host: " + ipAddress);
JOptionPane.showMessageDialog(sc, "Don't know about host: " + ipAddress, "Client", JOptionPane.PLAIN_MESSAGE);
return;
} catch (IOException e) {
System.err.println("Couldn't get I/O for " + "the connection to: " + ipAddress);
JOptionPane.showMessageDialog(sc, "Couldn't get I/O for the connection to: " + ipAddress, "Client",
JOptionPane.PLAIN_MESSAGE);
return;
}
JOptionPane.showMessageDialog(sc, "Comminucation is now activated", "Client", JOptionPane.PLAIN_MESSAGE);
sc.setCommunicationSocket(echoSocket);
sc.setOutStream(out);
sc.setInStream(in);
sc.getData();
}
}
I suggest you read up on java serialization. There is an example here. Basically, there is built in serialization support. Your class needs to implement Serializable. Then you use ObjectOutputStream and ObjectInputStream to write object.
You would be well advised to use libraries that shield you from the error prone low level socket programming.
For C++ look to Boost (http://www.boost.com) or ACE (http://www.cs.wustl.edu/~schmidt/ACE.html)
For Java I only found a document that talks about the acceptor pattern http://www.hillside.net/plop/plop99/proceedings/Fernandez3/RACPattern.PDF
But I am sure there's an implementation out somewhere
Your on the right track. A chat program is a good place to start learning about sockets.
What you want is to use the ObjectOutputStream and ObjectInputStream classes. You simply have to wrap your input stream / output stream with these filters. ObjectOutputStream has a method writeObject(), and the ObjectInputStream has a corresponding readObject() method.
Most serialization examples show reading and writing objects to a file, but the same can be done using a socket stream. See http://www.acm.org/crossroads/xrds4-2/serial.html
I didn't bother to read through your piles and piles of code, but in general you can't directly send objects over the network. Network communication is just bits and bytes. If you want to send objects, you'll need to serialize them on the sending side, and de-serialize them on the receiving side. There are tons of methods of serializing, eg JSON, XML, or even Java's built-in serialization support (only recommended if both the client and server will always be Java).
You may find this code to be a decent starting point for making your own class. These are two classes I made to somewhat abstract the work needed for TCP and UDP socket protocols:
http://code.google.com/p/hivewars/source/browse/trunk/SocketData.java
http://code.google.com/p/hivewars/source/browse/trunk/UDPSocket.java
Quick dislaimer: These are kind of versions of a feature full class, I just added functionality as I needed it. However, it could help you start.

Categories