i did try to test some stuff about Client/server communication in Java because i wanted to build a game with a client/server architecture.
So i read some articles and so on... it all worked till i tried to use the same classes and methods in a libGDX project client and the other as server was still the original java project.
than the fun started and i got class not found exceptions on the server side when the server where trying to read the object.
after that i tried to build client and server both as libGDX projects.
still the same error.
the serve:
package com.mygdx.game;
import java.io.IOException;
import java.net.*;
public class Server {
public static void main(String[] args) {
int port = 8800;
try {
ServerSocket serverSocket = new ServerSocket(port);
while (true) {
System.out.println("raedy");
Socket clientSocket = serverSocket.accept();
System.out.println(clientSocket+"verbunden!");
Worker worker = new Worker(clientSocket);
worker.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.mygdx.game;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
public class Worker extends Thread{
private Socket clientSocket;
public Worker(Socket clientsocket) {
this.clientSocket = clientsocket;
}
#Override
public void run() {
System.out.println("worker started");
try {
ObjectInputStream in= new ObjectInputStream(clientSocket.getInputStream());
Object obj = (Object) in.readObject();
if(obj instanceof Message) {
Message msg= (Message) in.readObject();
System.out.println("Client said: "+msg.getMessage());
}
System.out.println("input auf"+clientSocket.getLocalPort());
ObjectOutputStream out = new ObjectOutputStream(clientSocket.getOutputStream());
out.writeObject(new Message("Hello there!"));
System.out.println("output auf"+clientSocket.getPort());
} catch (IOException | ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package com.mygdx.game;
import java.io.Serializable;
public class Message implements Serializable{
private static final long serialVersionUID = 1L;
private String message;
public Message(String message) {
this.message = message;
}
public String getMessage(){
return message;
}
}
the client has the the same Message class and this:
package com.mygdx.game.desktop;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
import com.mygdx.game.MyGdxGame;
public class DesktopLauncher {
public static void main (String[] arg) {
int port = 8800;
try {
System.out.println("hello there!");
Socket client = new Socket("localhost", port );
ObjectOutputStream out = new ObjectOutputStream(client.getOutputStream());
out.writeObject(new Message("ich bin der client"));
System.err.println(client.getPort());
ObjectInputStream in = new ObjectInputStream(client.getInputStream());
Message msg= (Message) in.readObject();
System.out.println("Server said: "+msg.getMessage());
System.out.println(client.getLocalPort());
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
new LwjglApplication(new MyGdxGame(), config);
}
}
so my question is why does the same code work in normal java but when i build the same as a libGDX project and try the code there it doesn't work?
yes the message class is only for testing how a serializable object is transferred.
Later i want to send game commands via the object stream.
ps: you made it till the end! thank you :D
pps: the first try in java was without
Object obj = (Object) in.readObject();
if(obj instanceof Message)
I would really recommend you to use Kryonet instead of writing all the stuff from scratch yourself. It does exactly what you are trying to achieve, is mature and well tested with libGDX.
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.
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.
my client/server works perfectly for one message, then no matter what's next it says it's blank.
I believe the problem resolves in here or my commands class:
package MyServer;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
public class Main {
public static String line;
public static void main(String[] args){
while(true){
try {
//Creates a socket to receive commands from!
Socket socket = new Socket("localhost", 7586);
//Uses that socket to create a Reader to read the commands!
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//Waits for Lines to be sent and then executes them!
while(true){
line = in.readLine();
if(line != null){
Commands.ReceiveCommand();
}else {
break;
}
}
} catch (UnknownHostException e){
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
or in my commands:
package MyServer;
import javax.swing.JOptionPane;
public class Commands {
static String command = (Main.line).toString(); //<--This was the problem, just had to move it into the method below.
public static void ReceiveCommand(){
if(command.equals("test")){
JOptionPane.showMessageDialog(null,"works","command: " + command,JOptionPane.WARNING_MESSAGE);
//System.out.println("WORKEDS MOFO");
command = "";
}else{
JOptionPane.showMessageDialog(null,"not recognized","command: " + command,JOptionPane.WARNING_MESSAGE);
//System.out.println("no bueno");
//System.out.println("line is " + command);
command = "";
}
}
}
Edit: For some reason when debugging, command is just blank no matter what after it's been used once, so it might be in my main server class:
package MyClient;
import java.util.List;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class Main {
//Sets the Port
final static int PORT = 7591;
//Creates a list of Connected Clients
static List<Socket> connectedClients = new ArrayList<Socket>();
public static void main(String[] args){
//Creates a Thread to Send Messages to connectedClients
new Thread(new messageThread()).start();
try {
//Creates the ServerSocket
ServerSocket serverSocket = new ServerSocket(PORT);
while(true){
//Waits for a Connection and Accepts it...
Socket clientSocket = serverSocket.accept();
System.out.println("A Client has connected!");
//Adds it to the List
connectedClients.add(clientSocket);
}
} catch (IOException e) {
e.printStackTrace();
}
} }
and the messageThread:
package MyClient;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class messageThread implements Runnable {
public void run() {
while(true){
System.out.println(">>");
Scanner in = new Scanner(System.in);
String command = in.nextLine();
for(Socket clientToSendCommand : Main.connectedClients){
try {
PrintWriter commandWriter = new PrintWriter(clientToSendCommand.getOutputStream());
commandWriter.println(command);
commandWriter.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
This dosen't work, because th line
static String command = (Main.line).toString();
in the Commands-class is executed exactly once, when the Commands-class is first referenced.
When the second command is send, the class was already referenced, so this line is not executed again.
To solve this put the line inside the method, or - much better - pass it as a parameter to the method.
P.S.: Have you mixed up the packages? The class with the ServerSocket should be the server and thus be in the MyServer package. :-)
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
i try to program a part of a university research project about multi client - server socket programming.my code works as well as so that i give valide result but the problem is that evalutor of our group said that my code have not a good speed on connection for data transfer.i will be thankfull if you found the problem(s) in my code that cause this issue.
server part:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import j
ava.io.PrintStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
/**
*
*/
/**
* #author Sina
*
*/
public class BoxServer {
ServerSocket serversocket;
static ThreadHandler t[]=new ThreadHandler[100];
static int size=0;
static ArrayList<Message> messagebox=new ArrayList<Message>();
public static void main(String[] args) {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(79);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
while(true)
{
try{
//InetAddress inetadress=InetAddress.getLocalHost();
//System.out.println(inetadress);
//System.out.println(inetadress.getHostName());
//System.out.println(inetadress.getHostAddress());
Socket socket=serverSocket.accept();
if(socket==null)
{
System.out.println("null");
}
t[size]=new ThreadHandler(socket,"username");
size++;
t[size-1].start();
}
catch(UnknownHostException e){
System.out.println("salam s");
System.out.println(e.getMessage());
}
catch (IOException e) {
System.out.println("bye s");
System.out.println(e.getMessage());
}
}
}
}
class ThreadHandler extends Thread{
private String socname;
Socket mySocket;
ObjectInputStream inp;
ObjectOutputStream outp;
public ThreadHandler(Socket s,String socketName)
{
this.mySocket=s;
this.socname=socketName;
}
public void run()
{
try {
inp=new ObjectInputStream(mySocket.getInputStream());
outp=new ObjectOutputStream(mySocket.getOutputStream());
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
while(true)
{
System.out.println("thread run");
System.out.println(mySocket.getLocalPort());
System.out.println(mySocket.getLocalAddress());
try {
// System.out.println("my socket:"+mySocket.getOutputStream());
System.out.println(mySocket.isConnected());
System.out.println(inp.available());
System.out.println("inp = "+inp);
System.out.println("reeead "+ inp.readObject());
Message mess=(Message)inp.readObject();
System.out.println("dsd");
System.out.println("mess: "+mess);
BoxServer.messagebox.add(mess);
if(mess.getReceiver().equals("system-use:code=1"))
{
System.out.println(mess.getSender()+" wants to see his/her Inbox");
}
//mySocket.close();
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("bug dar thread");
e.printStackTrace();
}
}
}
}
client part
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
import java.util.TimerTask;
import java.util.concurrent.ScheduledExecutorService;
import javax.swing.Timer;
public class Main {
/**
* #param args
*/
static Socket socket=new Socket();
public static void main(String[] args) {
System.out.println("newuser(n) or login(l)");
Scanner scanner=new Scanner(System.in);
String typeOfOperation=scanner.nextLine();
if(typeOfOperation.equals("n"))
{
}
else
if(typeOfOperation.equals("l"))
{
try {
socket = new Socket("127.0.0.1",79);
final ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in=new ObjectInputStream(socket.getInputStream());
while(true)
{
Thread timer=new Thread()
{
public void run()
{
while(true)
{
Message temp=new Message();
temp.setReceiver("system-use:code=1");
temp.setSender("username");
try {
out.writeObject(temp);
sleep(5000);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (InterruptedException e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
};
timer.start();
String username=scanner.nextLine();
String to=scanner.nextLine();
String body=scanner.nextLine();
Message all=new Message();
all.setText(body);
all.setReceiver(to);
all.setSender(username);
System.out.println("you connected to system");
System.out.println(socket);
System.out.println("now should write");
out.writeObject(all);
System.out.println("ghable threAD");
}
// socket.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
System.out.println("salaam c");
System.out.println(e.getMessage());
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("bye c");
System.out.println(e.getMessage());
}
}
else
{
System.out.println("bad operation. try again!");
}
}
}
Message class(Entity only not important i think!):
import java.io.Serializable;
public class Message implements Serializable{
String sender;
String receiver;
String text;
boolean delivered=false;
public void delived()
{
this.delivered=true;
}
private String tostringOfClass;
public void setReceiver(String receiver) {
this.receiver = receiver;
}
public void setSender(String sender) {
this.sender = sender;
}
public void setText(String text) {
this.text = text;
}
public String getReceiver() {
return receiver;
}
public String getSender() {
return sender;
}
public String getText() {
return text;
}
public String toString()
{
tostringOfClass="sender : "+sender+" \n"+"receiver : "+receiver+" \n"+"message: "+text;
return tostringOfClass;
}
}
Your evaluator missed something much more important: it doesn't work. You are calling readObject() twice per loop in the server, but all you do with the first result is print it out with System.out.println(). So your code is missing every odd object.
There isn't much you could do to improve the speed of this. He probably wants you to interpose a BufferedOutputStream between the ObjectOutputStream and the socket, and similarly for BufferedInputStream. However the object streams already run their own buffers, so this is probably a waste of time. He might also want you to use large socket send and receive buffers, if you've been taught about those: see Socket.setXXXBufferSize(). Set them to at least 32k. He might also be anti-Serialization, but for this application I don't see that it makes much difference. This is an interactive application, and the messages are small, so the speed over the network is basically irrelevant. You can only type so fast.
You should also close in the client when the user types whatever it is that tells the program to stop, and in the server you must catch EOFException, before IOException, and close the socket and break out of the read loop when you get it.
Also printing out Socket.isConnected() yields no useful information. The socket is always connected at the points you print it at. This method is not a health-check for the connection, it only tells you about the state of your Socket. Not the same thing.
Your evaluator seems to me to be focussing on entirely the wrong thing.
I'm not sure how much time you would want to invest in optimizing your Socket code, but ZMQ http://www.zeromq.org/ has helped greatly in removing latency and optimizing the Bandwidth usage.
However, in simpler notes. Try not to use ObjectOutputStream they are one layer above. Go immediately for DataInputStream and DataOutputStream (Maybe also BufferedInputStream) It's been a while for me, so I'm rusty. But since you are sending strings, you don't need to do Object Serialization along with it.
You said, your time is being lost in data transfer as well. But consider not creating a new thread on each connection and use thread pools.
and Salam.
I would really appreciate help with my program. It is some sort of chat server with multiple clients.
Here's the server code:
package com.server;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static int PORT;
private ServerSocket server;
private Socket socket;
public Server(int port) throws IOException {
PORT = port;
server = new ServerSocket(PORT);
System.out.println("server started");
try {
while (true) {
socket = server.accept();
try {
new ServeClient(socket);
} catch (IOException e) {
socket.close();
}
}
} finally {
server.close();
}
}
public static void main(String[] args) throws IOException {
int port = Integer.parseInt(args[0]);
Server server = new Server(port);
}
}
I start the server and then create a Client. The server receives connection socket from socket
and creates a ServeClient Thread.
Here's ServeClient code:
package com.server;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Enumeration;
import java.util.Vector;
import com.gui.WindowManager;
public class ServeClient extends Thread {
private final Socket socket;
private BufferedReader in;
private PrintWriter out;
private String msg;
public static final String ENDSTRING = "END";
public static Vector clients = new Vector();
public ServeClient(final Socket socket) throws IOException {
this.socket = socket;
System.out.println("socket " + socket);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream())), true);
start();
}
public void run() {
try {
clients.add(this);
while (true) {
msg = in.readLine();
if (msg == ENDSTRING)
break;
broadcast(msg);
}
System.out.println("closing...");
} catch (IOException e) {
System.err.println("IO EXCEPTION");
} finally {
try {
socket.close();
} catch (IOException e) {
System.err.println("SOCKET NOT CLOSED");
}
}
}
#SuppressWarnings("deprecation")
public void broadcast(String msg) {
synchronized (clients) {
Enumeration<ServeClient> e = clients.elements();
while (e.hasMoreElements()) {
ServeClient serveClient = e.nextElement();
try {
synchronized (serveClient.out) {
serveClient.out.println(msg);
}
} catch (Exception eee) {
serveClient.stop();
}
}
}
}
}
What i get is a NullPointerException when ServeClient invokes run() method
server started
socket Socket[addr=/127.0.0.1,port=51438,localport=8888]
Exception in thread "Thread-0" java.lang.NullPointerException
at com.server.ServeClient.run(ServeClient.java:33)
line 33 is the line with first "try" statement in ServeClient run() method
com.server.ServeClient.run(ServeClient.java:33)
I don't believe that it's happening at the try.
Open up an IDE, turn on debugging, and step through until you can see what's happening. That's the fastest way to figure out what you've missed.
There's an object that you're assuming is fine that is not. Find it.
Here's an example of how to do this properly:
http://www.kodejava.org/examples/216.html
Your problem is with the order in which static instance variables are initialised. Try doing something like:
...
private static Vector clients = null;
...
if (clients==null) {
clients = new Vector(); // consider putting this in a synchronized block
}
before you add the client to the vector.
Sorry for necroing such an old issue but it seemed like this problem wasn't resolved, so I'll give a bit of input from my end.
I've had a similar problem and the compiler also kept telling me that the problem was at the start() method. However, when I commented out the thread part and just ran the code on the same thread as the UI, the compiler directed me to the real source of the problem: the code inside the thread.
After making sure the code didn't give an error, I enclosed the code with the original thread code, and it stopped giving me the NullPointerException error.
Hope this helps someone along the way.
Remove the duplicate class declaration in JPanel.
I was trying to run a timer thread that updated a clock in the main application window.
I had created the JFrame with Eclipse/WindowBuilder and had followed a tutorial on how to make a timer. I had copied the declaration of the textfield into the class declaration to make it available for the entire class, but forgot to remove the Class Id in front of the widget definition. So it still initialized the local instance and not the global one. Thus when I accessed the global one it was still null.