I want to ask why the server is showing only the first time one of the clients send data ,my intent is to have two clients and just want to send some integer ,the server to read it and then send it back to the other client and then to wait the this client to send info and send it to the other client (toggling them).But only the first time the data is sended ,it is read on the server ?
Server :
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
private ServerSocket serv;
private DataInputStream inFromClient1;
private DataOutputStream outToClient1;
private DataInputStream inFromClient2;
private DataOutputStream outToClient2;
public Server(){
try {
serv=new ServerSocket(8000);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void listen() throws IOException{
System.out.println("Listening for connections");
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
while(true){
Socket sock1;
Socket sock2;
try {
sock1 = serv.accept();
sock2=serv.accept();
handleSession(sock1,sock2);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
}
public void handleSession(Socket s1,Socket s2) throws IOException{
DataInputStream in1=new DataInputStream(s1.getInputStream());
DataOutputStream out1=new DataOutputStream(s1.getOutputStream());
DataInputStream in2=new DataInputStream(s1.getInputStream());
DataOutputStream out2=new DataOutputStream(s1.getOutputStream());
while(true){
int inint1=in1.readInt();
System.out.println("Recived from 1 " + inint1);
System.out.println("Sending to 2 ");
out2.writeInt(in1.readInt());
int inint2=in2.readInt();
System.out.println("Recived from 2 " + inint2);
System.out.println("Sending to 1 ");
out1.writeInt(inint2);
}
}
public static void main(String[] args) throws IOException {
new Server().listen();
}
}
Client :
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Client extends JFrame implements ActionListener{
private JPanel mainPanel;
private JButton[] buttons;
private Socket socket;
private int number;
private DataInputStream fromServer;
private DataOutputStream toServer;
private boolean myTurn=true;
public Client() throws UnknownHostException, IOException{
mainPanel=new JPanel(new GridLayout(3,3));
socket=new Socket("localhost",8000);
add(mainPanel);
addbuttons();
setSize(new Dimension(500,400));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
private void addbuttons(){
buttons=new JButton[9];
for(int i=1;i<10;i++){
buttons[i-1]=new JButton("Rectangle " + i);
buttons[i-1].addActionListener(this);
mainPanel.add(buttons[i-1]);
}
}
public void actionPerformed(ActionEvent arg0) {
JButton butt=(JButton) arg0.getSource();
String str=butt.getText();
String[] splitStr=str.split(" ");
number=Integer.parseInt(splitStr[1]);
System.out.println(number);
}
public void start() throws IOException{
fromServer=new DataInputStream(socket.getInputStream());
toServer=new DataOutputStream(socket.getOutputStream());
new Thread(new Runnable() {
#Override
public void run() {
Scanner in=new Scanner(System.in);
while(true){
System.out.println("Write some integer");
int inint=in.nextInt();
System.out.println("Before " + myTurn);
if(myTurn){
try {
toServer.writeInt(inint);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
myTurn=false;
}
else{
int fromServint=0;
try {
fromServint=fromServer.readInt();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Recived integer " + fromServint);
buttons[fromServint].setText("Some new Text");
myTurn=true;
}
System.out.println("After " + myTurn);
}
}
}).start();
}
public static void main(String[] args) throws UnknownHostException, IOException {
new Client().start();
}
}
Looks like you're reading 2 integers from client 1 (guessing it's a typo) so
try changing
out2.writeInt(in1.readInt());
to
out2.writeInt(inint1);
Also, as #JohnBollinger mentioned,
Separate Data*Streams are created, but both sets are connected to socket s1, instead of one set to each socket.
DataInputStream in1=new DataInputStream(s1.getInputStream());
DataOutputStream out1=new DataOutputStream(s1.getOutputStream());
DataInputStream in2=new DataInputStream(s1.getInputStream());
DataOutputStream out2=new DataOutputStream(s1.getOutputStream());
All streams here are referencing the same client.
You are using blocking sockets. For that reason, when you call any kind of "read" method, it will block until data is received from the client.
So, one thread is not enough. The first read will block, the second read will never be executed unless the first client actually sent something.
Solution 1: Use one thread per socket connection (recommended, because easier).
Solution 2: Use non-blocking sockets (not recommended, difficult but good for certain performance critical scenarios).
Look here:
int inint1=in1.readInt();
System.out.println("Recived from 1 " + inint1);
System.out.println("Sending to 2 ");
out2.writeInt(in1.readInt());
First you read an int from the first client. Then you print some stuff and read a second int from the same client. But the client waits for a int from the server and therefore sends no second, so the server blocks.
Replace the last line of the code above with out2.writeInt(inint1); and see if it works. I haven't read all of the code, so I am not sure if there is another mistake.
Related
So, I'm having an issue with a project of mine. I'm writing a multiplayer lobby system which will enable multiple users to join a lobby, readying themselves by pressing a key. The issue that I'm facing is when two players is readying themselves, the lobby is only printing out a message for the last player who readied themselves. The system is built up in the following way.
Main Server
package master;
import java.net.*;
import java.io.*;
import java.util.*;
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import main.Lobby;
public class MainServer {
public static final int PORT = 4444;
public static final String HOST = "localhost";
public ArrayList<Lobby> serverList = new ArrayList<>();
public static void main(String[] args) throws IOException, ClassNotFoundException {
new MainServer().runServer();
}
public void runServer() throws IOException, ClassNotFoundException {
// Creating the server
ServerSocket serverSocket = new ServerSocket(PORT);
System.out.println("Main Server initiated.");
while (true) {
Socket socket = serverSocket.accept();
try {
// Establishing the connection to the Lobby server and then adding it to its list
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
objectOutputStream.writeObject("Server created successfully.");
Lobby s = (Lobby) objectInputStream.readObject();
this.serverList.add(s);
System.out.println("Server \"" + s.name + "\" added to game list.");
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
The lobby
package main;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.Semaphore;
import master.MainServer;
/**
* The Class Server.
*/
public class Lobby implements Serializable {
private static final long serialVersionUID = -21654L;
public static final int PORT = 4445;
public static final int MAX_USERS = 5000;
public static final String HOST = "localhost";
public String name = "Lobby Server";
public int clientNumber;
public int playerNumberReady = 0;
public boolean allPlayersReady = false;
public boolean OddurIsNice = false;
public static void main(String[] args) throws IOException, ClassNotFoundException {
Lobby s = new Lobby();
s.runServer();
}
public void runServer() throws IOException, ClassNotFoundException {
registerServer();
new Thread( () -> {
try {
ServerSocket serverSocket = new ServerSocket(PORT);
System.out.println("Server waiting for connections...");
while (true) {
Socket socket = serverSocket.accept();
System.out.println("User 1 is now connected");
clientNumber++;
new ObjectOutputStream(socket.getOutputStream()).writeObject("You are connected man");
Socket socket2 = serverSocket.accept();
System.out.println("User 2 is now connected");
clientNumber++;
// ObjectOutputStream objectOutputStream2 = new ObjectOutputStream(socket2.getOutputStream());
// objectOutputStream2.writeObject("You are player number " + clientNumber + ". Waiting for other players to join");
new ServerThread(socket, socket2).start();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}).start();
}
private void registerServer() throws UnknownHostException, IOException, ClassNotFoundException {
// Method for establishing a connection to the MainServer
Socket socket = new Socket(MainServer.HOST, MainServer.PORT);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
objectOutputStream.writeObject(this);
System.out.println((String) objectInputStream.readObject());
}
public class ServerThread extends Thread {
public Socket socket = null;
public Socket socket2 = null;
ServerThread(Socket socket, Socket socket2) {
this.socket = socket;
this.socket2 = socket2;
}
public void run() {
try {
// This method is for when the client want's to connect to the lobby
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
System.out.println("User 1 is now connected");
ObjectInputStream objectInputStream2 = new ObjectInputStream(socket2.getInputStream());
ObjectOutputStream objectOutputStream2 = new ObjectOutputStream(socket2.getOutputStream());
System.out.println("User 2 is now connected");
BoardGameClient joined = (BoardGameClient) objectInputStream.readObject();
System.out.println(joined.name + " is now connected.");
while(true) {
objectOutputStream.writeObject("You joined the server.");
objectOutputStream.writeObject("You are player Number " + 1);
objectOutputStream.writeObject("Press '1' if you are ready");
objectOutputStream2.writeObject("You joined the server.");
objectOutputStream2.writeObject("You are player Number " + 2);
objectOutputStream2.writeObject("Press '1' if you are ready");
if(objectInputStream.readObject().equals(1)) {
playerNumberReady++;
}
if(objectInputStream2.readObject().equals(1)) {
playerNumberReady++;
}
if(playerNumberReady != 2) {
allPlayersReady = false;
} else {
allPlayersReady = true;
}
if (allPlayersReady == false) {
objectOutputStream.writeObject("Waiting...");
objectOutputStream2.writeObject("Waiting...");
}
if (allPlayersReady == true) {
objectOutputStream.writeObject("Lets GO");
objectOutputStream2.writeObject("Lets GO");
}
while (true) {
System.out.println(objectInputStream.readObject());
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
And the client
package main;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
import java.util.concurrent.Semaphore;
import master.MainServer;
public class BoardGameClient implements Serializable {
private int playerName;
private static final long serialVersionUID = -6224L;
public String name = "User";
private transient Socket socket;
public transient Scanner input = new Scanner(System.in);
public static void main(String[] args) {
BoardGameClient c = new BoardGameClient();
if (args.length > 0) {
c.name = args[0];
}
try {
c.joinServer();
} catch (ClassNotFoundException | IOException e) {
System.out.println("Failed to join server.");
e.printStackTrace();
}
}
public void joinServer() throws UnknownHostException, IOException, ClassNotFoundException {
socket = new Socket(Lobby.HOST, Lobby.PORT);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
while(true) {
objectOutputStream.writeObject(this);
BufferedReader inputReader = new BufferedReader(new InputStreamReader(System.in));
System.out.println(objectInputStream.readObject());
System.out.println(objectInputStream.readObject());
System.out.println(objectInputStream.readObject());
int ready = input.nextInt();
objectOutputStream.writeObject(ready);
System.out.println(objectInputStream.readObject());
objectOutputStream.writeObject(name + ": " + inputReader.readLine());
}
}
}
I sincerely hope, that someone will be able to help me out <3
Firstly, there's a few things that bug me about this code. Not to sound condescending but you need to avoid rewriting code as much as possible. What happens if you want 3 or more players in the future? Currently you'd have to manually create a whole socket eg socket3, and then rewrite all the code you've already written. This is bad. You've manually spent the time creating 2 sockets and then created 2 streams for both of these sockets etc etc.
This can be automated don't you think?
Secondly, you have a lot of public variables. Unless they are static and final, for the most part you should keep variables as private.
I've tinkered with your lobby class as seen below, which is more scalable. It's not perfect by any means, but I feel illustrates the direction of improvement you should be heading for. Look up SOLID OOP principles, they'll help you guaranteed.
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* The Class Server.
*/
public class Lobby implements Serializable {
private static final long serialVersionUID = -21654L;
public static final int PORT = 4445;
public static final int MAX_USERS = 5000;
public static final String HOST = "localhost";
private static final int MIN_USERS = 2;
private String name = "Lobby Server";
private int clientNumber;
private boolean gameRunning = false;
// set of client connections
private final Set<ServerThread> clientConnectionThreads = new LinkedHashSet<>();
public static void main(String[] args) throws IOException, ClassNotFoundException {
Lobby s = new Lobby();
s.createLobby();
}
public void createLobby() throws IOException, ClassNotFoundException {
// waits for all players to ready up in a different thread
new Thread(this::waitReady).start();
registerServer();
// Listens for clients
runServer();
}
public void runServer() {
// closes serverSocket automatically in this way
try (ServerSocket serverSocket = new ServerSocket(PORT)) {
System.out.println("Server waiting for connections...");
long ids = 0;
while (!gameRunning) {
// accepts a new client connection
Socket socket = serverSocket.accept();
if (clientConnectionThreads.size() >= MAX_USERS) {
// tell user server is full and dont add the connection
} else {
// calculates the new id of the incoming player and adds them to the lobby
ids++;
this.clientConnectionThreads.add(new ServerThread(ids, socket));
System.out.println("User " + ids + " is now connected");
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
/*
* loops until every player is ready and there is enough players and then starts
* the game.
*/
public void waitReady() {
while (true) {
try {
if (areAllReady() && this.clientConnectionThreads.size() >= MIN_USERS) {
startGame();
return;
}
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// returns true if all users are ready
public boolean areAllReady() {
return clientConnectionThreads.stream().allMatch(ServerThread::isReady);
}
public void startGame() {
System.out.println("Starting game...");
this.gameRunning = true;
clientConnectionThreads.forEach(ServerThread::startGame);
// do game stuff
}
// i havent touched this function
private void registerServer() throws UnknownHostException, IOException, ClassNotFoundException {
// Method for establishing a connection to the MainServer
Socket socket = new Socket(MainServer.HOST, MainServer.PORT);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
objectOutputStream.writeObject(this);
System.out.println((String) objectInputStream.readObject());
}
public class ServerThread extends Thread {
private final Socket socket;
private final ObjectInputStream in;
private final ObjectOutputStream out;
private final long id;
boolean ready = false;
private ServerThread(long id, Socket socket) throws IOException {
// does some basic initialization
this.socket = socket;
this.id = id;
in = new ObjectInputStream(socket.getInputStream());
out = new ObjectOutputStream(socket.getOutputStream());
// starts this connection thread
this.start();
}
public boolean isReady() {
return ready;
}
public void run() {
try {
// sets up the client and waits for their input
BoardGameClient joined = (BoardGameClient) in.readObject();
System.out.println(joined.name + " is now connected.");
out.writeObject("You joined the server.");
out.writeObject("You are player Number " + id);
out.writeObject("Press '1' if you are ready");
out.flush();
// waits for user to return ready
while (!ready) {
try {
int input = in.readInt();
System.out.println("input: " + input);
ready = input == 1;
} catch (ClassCastException e) {
e.printStackTrace();
}
}
out.writeObject("Waiting for players...");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void startGame() {
// send client message etc etc
}
}
public String getName() {
return name;
}
}
I basically didn't change any of the other classes, except a few lines within the client class to make this work. (I've changed the ready input type from writeObject() to writeInt())
I haven't tested this for problems, but I know it works at least on a basic level.
I also suggest using writeUTS()/readUTS() instead of writeObject()/readObject() for sending and receiving Strings across streams as this will add extra complexity to the code.
So, i am trying to create a Client Server chat program. Since, i don't have an external server so my client and server will be hosted in my computer. Now, i was following online tutorials and created the Server side of the chat program but then i get an error while i test the Server side of the program. When i create the server socket, what port number should i put if i am using my computer. I used a random number and i get the following errors:-
Can someone please help me to fix the error or suggest me what should i do? Thanks
This is my Server class:-
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.*;
import java.io.*;
import java.awt.*;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class Server extends JFrame {
private JTextField usertext;
private JTextArea chatwindow;
private ObjectOutputStream output;
private ObjectInputStream input;
private ServerSocket server;
private Socket connection;
public Server()
{
super("Missy's Instant Messenger");//This sets the title of the messenger window
usertext = new JTextField(); //this is for creating the textfield where the user will enter data
usertext.setEditable(false);//this is set to false such that the user can only send message if he is connected to someone
usertext.addActionListener( //this activity is for sending the message when the user clicks on enter
new ActionListener(){
public void actionPerformed(ActionEvent event){
sendMessage(event.getActionCommand());
usertext.setText(" ");
}
/* private void sendMessage(String string) {
// TODO Auto-generated method stub
}*/
});
add(usertext,BorderLayout.NORTH);
chatwindow = new JTextArea();
add(new JScrollPane(chatwindow));
setSize(500,500);
}
public void startrunning(){
try {
server = new ServerSocket(6800,100);
//6789 is the port number and 100 is the number of people that can wait in the queue to connect to the server
while(true)
{
try{
waitforConnection();//this is to connect to the server
setupStreams();//setting up the input and output streams to send and receive messages
whilechatting();//this is allow to send messages using the input and output streams
}catch (Exception e)
{
showMessage("Connection has ended");//this will be displayed when the connection is ended by the server
}finally{
closecrap(); //close all the streams and sockets
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void waitforConnection() throws IOException
{
showMessage("waiting for someone to connect.....");
connection = server.accept(); //this will connect the server and the client
showMessage("Now connected to "+connection.getInetAddress().getHostName());
}
private void setupStreams() throws IOException
{
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
input = new ObjectInputStream(connection.getInputStream());
showMessage("Your streams are now set up......");
}
private void whilechatting() throws IOException
{
String message = "You are now connected";
sendMessage(message);
abletotype(true);
do{
try{
message = (String)input.readObject();
showMessage("\n" +message);
}catch(ClassNotFoundException e)
{
showMessage("wtf is that");
}
}while(!message.equals("CLIENT END"));
}
private void showMessage(final String a)
{
SwingUtilities.invokeLater(
new Runnable(){
public void run(){
chatwindow.append(a);
}
}
);
// System.out.println(a);
}
public void closecrap()
{
showMessage("\n Connections closing .....");
abletotype(false);
try{
output.close();
input.close();
connection.close();
}catch(IOException ioException)
{
ioException.printStackTrace();
}
}
public void sendMessage(String message)
{
try{
output.writeObject("SERVER - "+message);//this is where you put the message in the output stream
output.flush(); //flush out the junk if there is any left
showMessage("\nSERVER -"+message); //show Message in the chat window
}catch(Exception e)
{
chatwindow.append("\n ERROR sending the message dude");
}
}
private void abletotype(final Boolean t)
{
SwingUtilities.invokeLater(
new Runnable(){
public void run(){
usertext.setEditable(t);
}
}
);
}
}
Servertest class:-
import javax.swing.*;
public class ServerTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Server st = new Server();
st.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
st.startrunning();
}
}
References:- ThenewBoston.com
I am going to summarize what has been said in some of the comments, and add my own thoughts.
First and foremost, the port is likely already in use. Its probably not in use by your program from what you said, however some other program is using it or has it reserved. As far as I know there is no official use for port 100, so it is likely just another program you have installed on your machine. Also from the comments it seems you have fixed this by swapping to a different port.
Connection.close() should work fine for closing the connection. For more information check out this link: How can I close the socket in a proper way?
As far as your most recent comment goes - if the program is running but the UI is not appearing, you likely have another issue with the code unrelated to your posted issue. I might suggest attempting to debug it on your own from here now that the server is starting without the JVM_BIND error and see what you come up with.
I'm doing an exercise requires making a server - client chat program using Java Non-Blocking IO. At the moment, the way the program works is simple: when a client send a message to the server, the server (which already keep track of all the clients) echo the message back to all the clients.
This is my some parts of my server-side code:
public static ByteBuffer str_to_bb(String msg) {
try {
return encoder.encode(CharBuffer.wrap(msg));
} catch(Exception e) {
e.printStackTrace();
}
return null;
}
private static void broadcastMessage(String nickname, String message) {
System.out.println(">clientSocketChannels size " + clientSocketChannels.size());
Iterator clientSocketChannelsIterator = clientSocketChannels.iterator();
while (clientSocketChannelsIterator.hasNext()) {
SocketChannel sc = (SocketChannel) clientSocketChannelsIterator.next();
try {
ByteBuffer bb = str_to_bb(message);
System.out.println("bufferRemaining: " + bb.remaining()); // returns 2048
int writeResult = sc.write(bb);
System.out.println("writeResult: " + writeResult); // returns 2048
} catch (IOException e) {
e.printStackTrace();
}
}
}
The following is my client-side code:
import javax.swing.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
/**
* Created by ThaiSon on 7/6/2015.
*/
public class ChatRoomClientGUI {
private JTextArea textAreaMessages;
private JTextField textFieldMessage;
private JButton buttonSendMsg;
private JPanel jPanel1;
private JLabel txtFieldInfo;
private static InetAddress inetAddress;
private static final int PORT = 1234;
private static Socket socket = null;
private static Scanner input = null;
private static PrintWriter output = null;
private static ChatRoomClientGUI singleton;
public ChatRoomClientGUI() {
singleton = this;
buttonSendMsg.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
if (e.getButton() == MouseEvent.BUTTON1) {
String message = textFieldMessage.getText();
output.println(message);
textFieldMessage.setText("");
}
}
});
}
public static void main(String[] args) {
JFrame promptFrame = new JFrame();
Object nickname = JOptionPane.showInputDialog(promptFrame, "Enter your nickname:");
promptFrame.dispose();
JFrame frame = new JFrame("ChatRoomClientGUI");
frame.setContentPane(new ChatRoomClientGUI().jPanel1);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
System.out.println("> Client with nickname " + nickname);
try {
inetAddress = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
accessServer(nickname.toString());
}
private static void accessServer(String nickname) {
try {
socket = new Socket(inetAddress, PORT);
input = new Scanner(socket.getInputStream());
output = new PrintWriter(socket.getOutputStream(), true);
output.println(nickname); // Register nickname with the server
//TODO update the txtFieldInfo content
// Create a new thread to listen to InputStream event
InputStreamEvent inputStreamEvent = new InputStreamEvent(socket);
inputStreamEvent.start();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void handleInputStream(){
String response = input.nextLine();
System.out.println("TODO " + response);
singleton.textAreaMessages.append(response + "\n");
}
static class InputStreamEvent extends Thread{
Socket socket;
public InputStreamEvent(Socket socket){
this.socket = socket;
}
public void run(){
try {
InputStream inputStream = socket.getInputStream();
byte[] buffer = new byte[2048];
int read;
while (true){
if(inputStream.available() > 0){
handleInputStream();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
The problem I'm facing with now is that when I use a client (which works well with the old multithreaded server) to send message to the server, the client only get return the first message it sends. All the next responses from the server is empty (the server does send back, but only an empty message).
So my attempts to debug includes:
check if the messages from the client has reach the server or not. They does.
log the buffer.remaining() and socketChannel.write(buffer) result as shown above, all the log result seems to be normal to me.
Hope you guys can help me with this.
This:
if(inputStream.available() > 0){
Get rid of this test. With it, your client is smoking the CPU. Without it, it will block in readLine() as God intended.
Are you sure your server is still sending lines? with line terminators? If it isn't, readLine() will block forever looking for one, until end of stream or an exception occurs.
I referred the code explain by EJP on this link Java NIO Server/Client Chat App - sending data only by closing the socket
it solves my problem. use this code
import java.nio.channels.SocketChannel;
import java.nio.channels.Selector;
import java.nio.ByteBuffer;
import java.io.IOException;
import java.util.Scanner;
import java.nio.channels.SelectionKey;
import java.net.InetSocketAddress;
public class Client {
public static void main(String args[]) {
try {
ByteBuffer buf = ByteBuffer.allocate(200);
Scanner scanner = new Scanner(System.in);
Selector selector = Selector.open();
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_CONNECT|SelectionKey.OP_READ|SelectionKey.OP_WRITE);
boolean isConnected = socketChannel.connect(new InetSocketAddress("localhost", 5000));
if(isConnected) {
System.out.println("Connected, de-registering OP_CONNECT");
}
new Thread(new Runnable(){
private SocketChannel socketChannel;
private Selector selector;
public Runnable init(SocketChannel socketChannel, Selector selector) {
this.socketChannel = socketChannel;
this.selector = selector;
return this;
}
public void run() {
try {
ByteBuffer buf = ByteBuffer.allocate(200);
while(!Thread.interrupted()) {
int keys = selector.select();
if(keys > 0) {
for(SelectionKey key : selector.selectedKeys()) {
if(key.isConnectable()) {
boolean finishConnectResult = socketChannel.finishConnect();
socketChannel.register(this.selector, SelectionKey.OP_WRITE|SelectionKey.OP_READ);
System.out.println("Finished Connect : " + finishConnectResult);
}
if(key.isReadable()) {
int bytesRead = 0;
while((bytesRead = socketChannel.read(buf)) > 0) {
buf.flip();
while(buf.hasRemaining()) {
System.out.print((char)buf.get());
}
buf.clear();
}
if(bytesRead == -1) {
key.channel().close();
}
}
}
}
Thread.sleep(10);
}
} catch(IOException e) {
e.printStackTrace();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}.init(socketChannel, selector)).start();
while(true) {
while(scanner.hasNextLine()) {
buf.clear();
buf.put(scanner.nextLine().getBytes());
buf.flip();
socketChannel.write(buf);
buf.flip();
}
}
} catch(IOException e) {
e.printStackTrace();
}
}
}
I have done the mistake setting this flag
key.interestOps(SelectionKey.OP_READ);
)
instead of below.
use this
socketChannel.register(this.selector, SelectionKey.OP_WRITE|SelectionKey.OP_READ);
I have gone through a lot of threads and blogs/examples outside SO but I just can't get my code to work. The code is very similar to what others have posted but this thing just won't work .. Here is a brief outline of the code.
Server Class implements Runnable
Creates new ServerSocket(PORT, Numberof Users)
Uses serverSocket.Accept() to get the socket and stores it in ArrayList.
Sends a welcome message to socket The code uses print writer on OUTPUTSTREAM on Socket.
(this part actually works and I get the message back)
Client Class
socket = new Socket(localhost, PORT);
In a separate thread start reader which reads from socket.inputstream and puts it on chat window.
In a separate thread write to socket.output stream.
This is mostly same as server side code
So when I test the code. The server starts. The client opens up swing window. It connects to server. It gets the server welcome message back. But when I write something it does not return back the text that I just sent. it just stays at readLine and never come back. I had a similar issue in echoserver code which I fixed (thanks to SO !) using threads. Now both reader and writer are in separate thread, so I am not sure whats wrong.
Thanks in advance! Apologies if you think its a repeated thread but I just can't fix my code on my own !
Here is the full code:
Server Class:
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
public class ChatServer implements Runnable {
private static int port;
private static String ip_add;
private Socket socket;
private ArrayList<Socket> clients;
private ServerSocket ss;
public ChatServer(String ip_add_in, int port_in) {
// TODO Auto-generated constructor stub
port = port_in;
ip_add = ip_add_in;
clients = new ArrayList<Socket>();
}
#Override
public void run() {
// TODO Auto-generated method stub
System.out.println("ChatServer Start!!" + new Date() );
try {
ss = new ServerSocket(port, 10);
while(true){
socket = ss.accept();
System.out.println("ChatServer Accepts!!" + new Date() );
clients.add(socket);
sendWelcomeMessage();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void sendWelcomeMessage() {
try {
PrintWriter writer = new PrintWriter(socket.getOutputStream());
writer.println("Welcome To Chat Server");
writer.flush();
writer.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public class transmitMessages implements Runnable {
#Override
public void run() {
// TODO Auto-generated method stub
while(true){
if (ss.isBound()) {
for (Socket sock : clients) {
}
}
}
}
}
}
Client Class:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.*;
import javax.swing.*;
public class Chat1 {
JFrame frame;
JPanel msg_pan, chat_pan;
JButton send;
JTextArea type_area, chat_area;
private static String user;
private SendMsg send_action = new SendMsg();
private Socket writerSocket;
// private Socket readerSocket;
static String ip_address;
static int port;
private PrintWriter writer;
private ReaderThread readerRunner;
private SenderThread senderRunner;
Thread senderThread;
Thread readerThread;
public Chat1(String name){
user = name;
}
public void create_window() {
frame = new JFrame(user);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
chat_pan = new JPanel();
// Adding Main Chat Area
chat_area = new JTextArea(30,50);
chat_area.setEditable(false);
chat_area.setLineWrap(true);
JScrollPane chat_scroll = new JScrollPane(chat_area);
chat_scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
chat_scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
chat_pan.add(chat_scroll);
msg_pan = new JPanel();
send = new JButton("Send");
send.addActionListener(send_action);
type_area = new JTextArea(5,50);
type_area.setLineWrap(true);
JScrollPane type_scroll = new JScrollPane(type_area);
type_scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
msg_pan.add(type_scroll);
msg_pan.add(send);
msg_pan.setLayout(new BoxLayout(msg_pan, BoxLayout.X_AXIS));
frame.getContentPane().add(BorderLayout.SOUTH, msg_pan);
frame.getContentPane().add(BorderLayout.CENTER, chat_pan);
frame.setSize(600, 600);
frame.setVisible(true);
frame.pack();
}
public static void main(String ip_add_in, int port_in) {
// TODO Auto-generated method stub
ip_address = ip_add_in;
port = port_in;
Chat1 user1 = new Chat1("User1");
user1.startchat();
}
class SendMsg implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
String msg = type_area.getText();
if (msg != null) {
senderRunner = new SenderThread(msg);
senderThread = new Thread(senderRunner);
senderThread.start();
}
type_area.setText(null);
}
}
public void setup_connection() {
}
public void startchat(){
connect_socket();
create_window();
System.out.println("Window Done");
readerRunner = new ReaderThread();
readerThread = new Thread(readerRunner);
readerThread.start();
System.out.println("Thread Started");
}
public void connect_socket(){
try {
System.out.println("Start Chat" + new Date());
writerSocket = new Socket(ip_address,port);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public class ReaderThread implements Runnable {
InputStreamReader streamReader;
BufferedReader reader;
String msg;
public void run(){
try {
System.out.println("Entered ReaderThread Run");
streamReader = new InputStreamReader(writerSocket.getInputStream());
reader = new BufferedReader(streamReader);
while (true) {
msg = reader.readLine();
if (msg != null) {
chat_area.append(msg);
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Leaving ReaderThread Run");
}
}
public class SenderThread implements Runnable{
String msg;
public SenderThread(String msg_in){
msg = msg_in;
}
public void run(){
System.out.println("Entered SenderThread Run" + msg);
try {
if (writer == null) {
writer = new PrintWriter(writerSocket.getOutputStream());
}
System.out.println("Writer has Error-->" + writer.checkError());
writer.println(msg);
writer.flush();
writer.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
System.out.println("Sender Thread Run Exception 1");
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("Sender Thread Run Exception 2");
e.printStackTrace();
}
System.out.println("Leaving SenderThread Run");
}
}
}
Tester Class:
import java.util.*;
public class ChatTester {
public static void main(String[] args) {
// TODO Auto-generated method stub
ChatServer serverRunner = new ChatServer("127.0.0.1", 5000);
Thread serverThread = new Thread(serverRunner);
serverThread.start();
System.out.println("Server Started" + new Date());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Thread clientThread = new Thread() {
public void run() {
Chat1.main("127.0.0.1", 5000);
}
};
clientThread.start();
System.out.println("Client Started" + new Date());
}
}
You are closing the writer after every send, which also closes the underlying socket output stream. You can see this in your test output:
Writer has Error-->false (before first send)
Writer has Error-->false (before second send, output is already closed!)
Writer has Error-->true (before third send, second send failed because the stream is closed)
The server on the other hand does not listen for any incoming messages. It only sends the welcome message and then closes the output stream!
The server needs to keeps reading the input streams of the client sockets. When it receives a message, it should write it to the output streams of the clients.
Do not close the streams as long as you are communication with the clients.
Below is a simple example of how to receive messages and send a reply.
First remove writer.close() in both SenderThread and sendWelcomeMessage().
Start a new handler thread for each connection (note: starting a new thread for each connection might not be the best practice for "real" applications).
while(true){
socket = ss.accept();
System.out.println("ChatServer Accepts!!" + new Date() );
clients.add(socket);
sendWelcomeMessage();
(new Thread(new ClientHandler(socket))).start();
}
In the thread, listen for incoming messages and send them back.
public class ClientHandler implements Runnable {
private Socket socket;
private BufferedReader reader;
private BufferedWriter writer;
public ClientHandler(Socket socket)
{
this.socket = socket;
}
#Override
public void run() {
try
{
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String message = reader.readLine();
while (message != null)
{
writer.write(message + System.lineSeparator());
writer.flush();
message = reader.readLine();
}
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Note that the ClientHandler thread only echoes the received message back to the sender. In a real chat, these messages would be sent to all connected clients, for example in your transmitMessages class, that does not do anything at the moment.
I'm trying to make a MultiClient Chat Application in which the chat is implemented in the client window. I've tried server and client code for the same. I've got two problems:
A. I believe the code should work but, server to client connections are just fine but information isn't transferred between clients.
B. I need a way to implement private one-to-one chat in case of more than two clients, I've used a class to store the information of the Socket object returned for each connection being established, but I can't figure out how to implement it.
The server code is:
import java.io.*;
import java.net.*;
class ClientInfo {
Socket socket;
String name;
public ClientInfo(Socket socket, String name) {
this.socket = socket;
this.name = name;
}
}
public class server {
private ObjectInputStream input[] = null;
private ObjectOutputStream output[] = null;
private String value = null;
private static ServerSocket server;
private Socket connection = null;
private static int i = -1;
public static void main(String args[]) {
try {
server = new ServerSocket(1500, 100);
while (true) {
System.out.println("Waiting for connection from client");
Socket connection = server.accept();
i++;
System.out.println("Connection received from " + (i + 1) + " source(s)");
//System.out.println(i);
new ClientInfo(connection, "Client no:" + (i + 1));
innerChat inc = new server().new innerChat(connection);
}
} catch (Exception e) {
System.out.println("Error in public static void main! >>>" + e);
}
}// end of main!!!
class innerChat implements Runnable {
private Socket connection = null;
public innerChat(Socket connection) {
this.connection = connection;
Thread t;
t = new Thread(this);
t.start();
}
public void run() {
try {
output[i] = new ObjectOutputStream(connection.getOutputStream());
output[i].flush();
input[i] = new ObjectInputStream(connection.getInputStream());
} catch (Exception e) {
}
}
}
}
And the client code is
import java.net.*;
import java.io.*;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.*;
import java.awt.event.*;
public class ChatappClient {
private static int port = 1500;
JFrame window = new JFrame("Chat");
JButton sendBox = new JButton("Send");
JTextField inputMsg = new JTextField(35);
JTextArea outputMsg = new JTextArea(10, 35);
private ObjectInputStream input;
private ObjectOutputStream output;
public static void main(String[] args) throws Exception {
ChatappClient c = new ChatappClient();
c.window.setVisible(true);
c.window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
c.run();
}
public ChatappClient() {
inputMsg.setSize(40, 20);
sendBox.setSize(5, 10);
outputMsg.setSize(35, 50);
inputMsg.setEditable(true);
outputMsg.setEditable(false);
window.getContentPane().add(inputMsg, "South");
window.getContentPane().add(outputMsg, "East");
window.getContentPane().add(sendBox, "West");
window.pack();
sendBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
output.writeObject(inputMsg.getText());
outputMsg.append("\n" + "Client>>>" + inputMsg.getText());
output.flush();
} catch (IOException ie) {
outputMsg.append("Error encountered! " + ie);
}
inputMsg.setText("");
}
});
inputMsg.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
output.writeObject(inputMsg.getText());
outputMsg.append("\n" + "Client>>>" + inputMsg.getText());
output.flush();
} catch (IOException ie) {
outputMsg.append("Error encountered! " + ie);
}
inputMsg.setText("");
}
});
}
private void run() throws IOException {
Socket clientSocket = new Socket("127.0.0.1", port);
output = new ObjectOutputStream(clientSocket.getOutputStream());
output.flush();
input = new ObjectInputStream(clientSocket.getInputStream());
outputMsg.append("I/O Success");
String value = null;
while (true) {
try {
value = (String) input.readObject();
} catch (Exception e) {
}
outputMsg.append(value + "\n");
}
}
}
Your code looks like it could be improved quite a bit. Your main method for instance should have none of that code in it. It should start your Server class, and that's it (and note that class names should begin with an upper case letter as per Java standards which I strongly advise you to follow).
I'm trying to make a MultiClient Chat Application in which a Server does nothing but listen and create connections.
The Server is going to have to do more than that. It will need to create Clients, it will need to maintain a collection such as an ArrayList of Clients such as an ArrayList<ChatappClient> Otherwise how do you expect the Server to connect two Clients together?
I think that in all you're going to need to think the structure and connections of this program out in more depth before starting to write code.