I am writing an I/O communication between one server (GameServer) and three clients (GameClient). After the server accepts three clients, it starts a separate thread (HandlePlayer). The HandlePlayer class establishes ObjectInputStream and ObjectOutputStream with three clients.However, at this part, the program stopped (not terminated, but cannot execute any following codes, so I guess the thread may be blocked).
These are the source code of the three classes I mentioned above. I only kept parts relevant to the question
GameServer:
public class GameServer implements Runnable, ShareData {
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(PORT);
System.out.println("server start at port " + PORT);
// wait for players to connect
while (true) {
Socket player1 = serverSocket.accept();
System.out.println("player 1: " + player1.getInetAddress().getHostAddress());
Socket player2 = serverSocket.accept(); // connect to player 2
System.out.println("player 2: " + player2.getInetAddress().getHostAddress());
Socket player3 = serverSocket.accept(); // connect to player 3
System.out.println("player 3: " + player3.getInetAddress().getHostAddress());
// start the game
new Thread(new HandlePlayer(player1, player2, player3)).start();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread server = new Thread(new GameServer());
server.start();
}
}
HandlePlayer:
public class HandlePlayer implements Runnable, ShareData {
// three players
private Socket player1;
private Socket player2;
private Socket player3;
// communication with players
ObjectInputStream fromPlayer1;
ObjectOutputStream toPlayer1;
ObjectInputStream fromPlayer2;
ObjectOutputStream toPlayer2;
ObjectInputStream fromPlayer3;
ObjectOutputStream toPlayer3;
public HandlePlayer(Socket player1, Socket player2, Socket player3) {
this.player1 = player1;
this.player2 = player2;
this.player3 = player3;
}
// start the game
public void run() {
try {
// initialize communication connections
fromPlayer1 = new ObjectInputStream(player1.getInputStream());
toPlayer1 = new ObjectOutputStream(player1.getOutputStream());
fromPlayer2 = new ObjectInputStream(player2.getInputStream());
toPlayer2 = new ObjectOutputStream(player2.getOutputStream());
fromPlayer3 = new ObjectInputStream(player3.getInputStream());
toPlayer3 = new ObjectOutputStream(player3.getOutputStream());
// receive robot selections
char player1Robot = fromPlayer1.readChar();
char player2Robot = fromPlayer2.readChar();
char player3Robot = fromPlayer3.readChar();
// the game loop
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
GameClient
public class GameClient implements Runnable, ShareData {
private ObjectInputStream fromServer;
private ObjectOutputStream toServer;
private Scanner input = new Scanner(System.in);
private String host = "localhost";
// connect to server
private void connectToServer() {
try {
Socket socket = new Socket(host, PORT);
fromServer = new ObjectInputStream(socket.getInputStream());
toServer = new ObjectOutputStream(socket.getOutputStream());
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void run() {
try {
connectToServer();
} catch (Exception e) {
e.printStackTrace();
}
}
Firstly, I tried to run the GameServer in debug mode. It has no problem accepting the three socket connections from three separate clients. Then, after it invokes the HandlePlayer, the program stops at the line fromPlayer1 = new ObjectInputStream(player1.getInputStream());. It does not move on, but the program is not terminated.
enter image description here
o
Secondly, I changed all Object IO streams to Data IO streams (DataInputStream and DataOutputStream). Strangely, this time the program works and there is no unexpected stopping. I wonder what makes Object streams different?
Thanks for you reply. This is my first time posting questions on Stack Overflow, please remind me if I don't make myself clear.
I figured out this question on my own. It turns out when both the HandlePlayer and the GameClient are creating the ObjectInputStream, it produces a deadlock as both are waiting for the other's output. After I switched the orders in the GameClient class like this, it worked:
toPlayer1 = new ObjectOutputStream(player1.getOutputStream());
toPlayer2 = new ObjectOutputStream(player2.getOutputStream());
toPlayer3 = new ObjectOutputStream(player3.getOutputStream());
fromPlayer1 = new ObjectInputStream(player1.getInputStream());
fromPlayer2 = new ObjectInputStream(player2.getInputStream());
fromPlayer3 = new ObjectInputStream(player3.getInputStream());
Related
I'm new in Java Sockets, I have seen so many examples but I can't understand how to pass an argument from server to client and vice versa. My destination is to pass an Object that's why I'm using Object I/O Stream.
I have to classes Server and Player.
public class Server extends Thread{
public static final int TEST = 165;
ServerSocket serverSocket;
InetAddress address;
Player playerWhite;
public Server() {
start();
}
#Override
public void run() {
try
{
address = InetAddress.getLocalHost();
serverSocket = new ServerSocket(6000);
playerWhite = new Player();
System.out.println("server waits for players");
playerWhite.socket = serverSocket.accept();
playerWhite.start();
sendTestMessage(playerWhite);
}
catch (IOException ex)
{
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void sendTestMessage(Player player) throws IOException
{
ObjectOutputStream testToClient = new ObjectOutputStream(player.socket.getOutputStream());
testToClient.write(TEST);
testToClient.flush();
}
And the Player class:
public class Player extends Thread {
Socket socket;
Player() throws IOException
{
socket = new Socket(InetAddress.getLocalHost(), 6000);
}
#Override
public void run() {
try {
listenTestStream();
}
catch (IOException | ClassNotFoundException ex)
{
Logger.getLogger(CheckerPlayer.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void listenTestStream() throws IOException, ClassNotFoundException
{
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
int message = ois.readInt();
//To test
System.out.println("Server listened: " + message);
}
I execute it as create a Server object in the other class.
When I have testing this application I saw that sometimes client is faster than Server. Is it possible to make him "wait" for server response?
Thanks for your response.
EDIT 1: PROBLEM SOLUTION:
From outside we should create:
Player player = new Player(); // (class player extends from Thread)
player.start();
and delete the Player variable - is not necessary, we need only Socket so:
Server:
Socket playerWhiteSocket
public void run() {
try
{
serverSocket = new ServerSocket(PORT);
playerWhiteSocket = serverSocket.accept();
sendMessage(playerWhiteSocket, "Hello");
}
catch(IOException | ClassNotFoundException ex)
{}
public void sendMessage(Socket socket, String message) throws IOException
{
ObjectOutputStream testToClient = new ObjectOutputStream(socket.getOutputStream());
testToClient.writeObject(message);
testToClient.flush();
}
In Player class we need get method:
public String receiveMessage() throws IOException, ClassNotFoundException
{
//socket is a variable get from Player class socket = new Socket("severHost", PORT);
ObjectInputStream messageFromServer = new ObjectInputStream(socket.getInputStream());
String message = (String) messageFromServer.readObject();
return message;
}
I would recomment doing this public void start(){
try {
ServerSocket = new ServerSocket(this.port,10,this.localAddress);
// set timeout if you want
//this.clientServerSocket.setSoTimeout(timeout);
// infinity loop
while(true)
{
//wait for a client connection
Socket socket = ServerSocket.accept();
// start thread for every new client
Thread t = new Thread(new AcceptClients(this.socket));
t.start();
System.out.println(L"new client connected");
// call garbage collector and hope for the best
System.gc();
}
} catch (IOException e) {
System.out.println("IO Error");
e.printStackTrace();
}
}
and then in another class
public class AcceptClients implements Runnable{
// socket
private Socket socket;
public AcceptClients (Socket socket){
this.socket = socket;
}
#Override
public void run() {
// what happens if a client connect
}
}
I always use this and it works fine
Suggested changes.
Create ServerSocket only once. If you have done it, you won't get "Address already in use" error
After creating Server Socket, you thread should be in while (true) loop to accept connection from client.
Once you create a client socket, pass that socket to thread.
Now Player is used to send communication from server to client socket. So You need one more class like PlayerClient which create a socket to Server IP and Port. Now PlayerClient should create one more thread to handle IO operations like you have done from server. In this case, creating a socket is not in while loop from client side. It create a socket to server once. Now you can run this PlayerClient program from multiple machines.
If you are just sending just primitive type, use DataOutputStream & DataInputStream instead of ObjectStreams
This code will become like this
try
{
address = InetAddress.getLocalHost();
serverSocket = new ServerSocket(6000);
System.out.println("server waits for players");
while ( true){
Socket socket = serverSocket.accept();
Player playerWhite = new Player(socket);
sendTestMessage(socket);// Move this method to Player thread and change the signature of this method accordingly to accept a socket
}
}
catch (IOException ex)
{
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
Player.java
Player(Socket socket) throws IOException
{
this.socket = socket;
start();
}
Have a look at this chat example for better understanding.
Yep it is.
It should work if you put it in a endlees loop like that:
try
{
while(true){
address = InetAddress.getLocalHost();
serverSocket = new ServerSocket(6000);
playerWhite = new Player();
System.out.println("server waits for players");
playerWhite.socket = serverSocket.accept();
playerWhite.start();
sendTestMessage(playerWhite);
}
}
catch (IOException ex)
{
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
But I would not recommend to put this in a thread. Instead I would put the connection of a new client in a thread, so multiple clients can connect to the server
Here's the code for server side :
public class EchoServer {
public static void main(String[] args) {
int port = 8080;
try {
ServerSocket server = new ServerSocket(port);
Socket cliSocket = server.accept();
Scanner in = new Scanner(cliSocket.getInputStream());
PrintWriter write = new PrintWriter(cliSocket.getOutputStream(),true);
String message;
while((message=in.nextLine()) != null){
write.println(message+" added");
}
write.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
and here's the client side :
public class EchoClient {
public static void main(String[] args) {
String ip = "localhost";
int port = 8080;
try {
Socket client = new Socket(ip, port);
PrintWriter write = new PrintWriter(client.getOutputStream(), true);
Scanner in = new Scanner(client.getInputStream());
Scanner read = new Scanner(System.in);
String input;
while((input=read.nextLine()) != null){
write.println(input);
System.out.println("sent by server:" + in.nextLine());
}
write.close();
in.close();
read.close();
client.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Now when I run the server and then the client, it works. But if close the client app, and i run it once again, the server won't allow connection.
What is the solution in situations like this?
Your server program only accepts one client connection and exits after handling the connection.
If you want it to repeatedly accept client connections, you need to use a loop around the code you have in main()
The easiest solution is that every time you accept a connection, you launch a new thread to handle the client. That would allow you to handle any number of clients, and also deal with general TCP issues like sockets that are stuck open when clients are killed.
Something like this:
public class EchoServer {
public static void main(String[] args) {
int port = 8080;
ServerSocket server = new ServerSocket(port);
while (true) {
//wait for next client to connect
Socket cliSocket = server.accept();
//hand off socket to another thread
MyHandler handler = new MyHandler(cliSocket);
Thread clientHandler = new Thread(handler);
clientHandler.start();
}
}
}
public class MyHandler implements Runnable {
public MyHandler(Socket cliSocket)
{
//store socket
}
#override
public void run()
{
while(true) {
//handle client comms
}
}
}
I read through SO a lot and I found many examples which were doing what I am trying to do. But I just can't find the issue in my code at all. May be I just need a fresh set of eyes to look at my code.
So with risk of being flagged for duplicate thread here is goes. I have a simple Java code. It opens a port. Connects a socket to that. gets the inputstream and outputstream. Puts some text to output stream and inputstream tries to read the text. When the mehtod for readLine is executed it does not return back to the code. It just keeps running and never comes back to main method.
import java.net.*;
import java.io.*;
import java.io.ObjectInputStream.GetField;
public class echoserver {
public static void main(String[] args) {
// TODO Auto-generated method stub
String hostName = "127.0.0.1";
// InetAddress.getLocalHost()
int portNumber = 5000;
ServerSocket ss = null;
Socket echoSocket = null;
try {
ss = new ServerSocket(portNumber);
echoSocket = new Socket(hostName, portNumber);
// echoSocket = ss.accept();
System.out.println("open");
System.out.println(echoSocket.isBound());
PrintWriter writer = new PrintWriter(echoSocket.getOutputStream());
for (int i = 0; i < 100; i++) {
writer.print("test String");
}
writer.flush();
// writer.close();
System.out.println("inputstream read");
DataInputStream is = new DataInputStream(echoSocket.getInputStream());
String fromStream = is.readLine();
System.out.println(fromStream);
System.out.println("bufferreader read");
BufferedReader reader = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
String fromReader = reader.readLine();
System.out.println(fromReader);
} catch (UnknownHostException ex1) {
// TODO Auto-generated catch block
System.out.println("EX1");
ex1.printStackTrace();
}
catch (IOException ex2) {
// TODO: handle exception
System.out.println("EX2");
ex2.printStackTrace();
}
finally {
try {
echoSocket.close();
ss.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
EDIT : Updated Code below... The only issue in this code is that while loop in Server.Run never ends. I looked for some other attributes (I remember something like isTextAvailable) but could not find it. The idea behind the code is to convert it into a chat client. needless to say its a struggle !
EDIT 2: I found the the issue. I never closed the socket from writer end so the listner kept on listening ! Thanks for help everyone !
clientsocket.close();
Added one line and it worked!
import java.net.*;
import java.io.*;
import java.io.ObjectInputStream.GetField;
import java.util.*;
public class echoserver {
static echoserver echo;
public static class Client implements Runnable {
Socket clientsocket;
String hostName = "127.0.0.1";
int portNumber = 5000;
static int onesleep = 0;
public void run(){
System.out.println("Client Run " + new Date());
try {
clientsocket = new Socket(hostName,portNumber);
PrintWriter writer = new PrintWriter(clientsocket.getOutputStream());
for (int i = 0; i < 10; i++) {
writer.println("test String " + i );
}
writer.flush();
clientsocket.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class Server implements Runnable {
public void run(){
System.out.println("Server Run" + new Date());
int portNumber = 5000;
ServerSocket ss = null;
Socket serversocket = null;
InputStreamReader streamReader;
try {
ss = new ServerSocket(portNumber);
serversocket = ss.accept();
System.out.println("bufferreader read " + new Date());
streamReader = new InputStreamReader(serversocket.getInputStream());
BufferedReader reader = new BufferedReader(streamReader);
String fromReader;
System.out.println(reader.ready());
System.out.println(reader.readLine());
while ((fromReader = reader.readLine()) != null) {
System.out.println(fromReader);
}
System.out.println("After While in Server Run");
} catch (IOException ex_server) {
// TODO Auto-generated catch block
System.out.println("Server Run Error " + new Date());
ex_server.printStackTrace();
}
finally {
try {
serversocket.close();
ss.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("open" + new Date());
System.out.println(serversocket.isBound());
}
}
public void go(){
Server server = new Server();
Thread serverThread = new Thread(server);
serverThread.start();
Client client = new Client();
Thread clientThread = new Thread(client);
clientThread.start();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
echo = new echoserver();
echo.go();
}
}
I had prepared a version of this post earlier, but based on your last comment in the other answer, it seems you have already figured it out. I'll posting this anyways, in case it is of any help.
The broad answer is that your class, as you currently have it, effectively represents both the client-side AND server-side portions within the same thread / process. As you've seen, you're able to write your data to the outbound (or client-side) socket, but the server-side component never gets a chance to listen for incoming connections.
Consequently, when you attempt to read data from the inbound (or server-side) socket's input stream, nothing exists because nothing was received. The readline() method ultimately blocks until data is available, which is why your program seems to hold at that point. Additionally, like haifzhan said, creating a new socket using new Socket(...) doesn't establish the connection, all you have is a socket with nothing in the stream.
The ServerSocket#accept method what you need to use in order to listen for connections. This method will create the socket for you, from which you can attempt to read from its stream. Like haifzhan said, that method blocks until a connection is established, which is ultimately why it cannot function properly in a single-threaded environment.
To do this within the same application, you'll simply need to separate the components and run them in separate threads. Try something like the following:
public class EchoClient {
public static void main(String[] args) throws InterruptedException {
new Thread(new EchoServer()).start(); // start up the server thread
String hostName = "localhost";
int portNumber = 5000;
try {
Socket outboundSocket = new Socket(hostName, portNumber);
System.out.println("Echo client is about to send data to the server...");
PrintWriter writer = new PrintWriter(outboundSocket.getOutputStream());
for (int i = 0; i < 100; i++) {
writer.print("test String");
}
System.out.println("Data has been sent");
writer.flush();
outboundSocket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
And the server component, which operates as a separate thread:
public class EchoServer implements Runnable {
public void run(){
try {
ServerSocket ss = new ServerSocket(5000);
System.out.println("Waiting for connection...");
Socket inboundSocket = ss.accept();
System.out.println("inputstream read");
DataInputStream is = new DataInputStream(inboundSocket.getInputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String fromStream = reader.readLine();
System.out.println(fromStream);
System.out.println("bufferreader read");
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
You did not connect to any client side socket...
From Writing the Server Side of a socket:
The accept method waits until a client starts up and requests a
connection on the host and port of this server. When a connection is
requested and successfully established, the accept method returns a
new Socket object which is bound to the same local port and has its
remote address and remote port set to that of the client. The server
can communicate with the client over this new Socket and continue to
listen for client connection requests on the original ServerSocket.
ss = new ServerSocket(portNumber);
echoSocket = new Socket(hostName, portNumber)
// echoSocket = ss.accept();
You should not use new Socket(host, port) to create a echoSocket, the ss.accept() is the correct way to establish the server client connection.
The reason it hangs because your code above(echoSocekt = ss.accept();) is not correct so the following will not be availalbe
DataInputStream is = new DataInputStream(echoSocket.getInputStream());
If you invoke is.available(), it will return 0 which means 0 bytes can be read from.
Read the link I provided, check EchoServer.java and EchoClient.java, and you will estiblish your own connection
I've got a simple client and server that I've written to teach myself a bit of networking. The way it's set up is I've got a main server class which will deal with creating/destroying sockets, and the ConnectionThread class that represents each connection (each of which is given its own thread). The client is super simple.
The problem lies in creating the input/output streams in the ConnectionThread class. I'm not sure exactly what the problem is, but it crashes when the simple test client tries to connect, giving me this:
~~MMO Server Alpha .1~~
Constructed Server
Server Initialized, preparing to start...
Server preparing to check if it should be listening...
Server should be listening, continuing as planned.
ServerSocket passed to ConnectionThread: ServerSocket[addr=0.0.0.0/0.0.0.0,localport=6969]
Constructing ConnectionThread.
Socket[addr=/10.0.1.10,port=55332,localport=6969]
ConnectionThread constructed.
Exception in thread "main" java.lang.NullPointerException
at ConnectionThread.init(ConnectionThread.java:65)
at Server.listen(Server.java:98)
at Server.start(Server.java:62)
at Server.main(Server.java:122)
ConnectionThread added to queue.
Establishing in and out streams:
null
Here are the classes (amended for brevity):
public class Server {
int PORT;
boolean shouldListen;
ArrayList<ConnectionThread> connections = new ArrayList<ConnectionThread>();
ServerSocket serverSocket;
public Server() {
try {
PORT = 6969;
shouldListen = true;
serverSocket = new ServerSocket(PORT);
}
catch (IOException e) {
System.out.println("Error in server constructor.");
System.exit(1);
}
}
public void start() {
System.out.println("Server preparing to check if it should be listening...");
listen();
System.out.println("Server finished listening.");
}
public void listen() {
while (shouldListen) {
ConnectionThread conn = null;
System.out.println("Server should be listening, continuing as planned.");
try {
conn = new ConnectionThread(serverSocket);
}
catch (Exception e) {
System.out.println("____Error constructing ConnectionThread. Could there be another instance of the server running?");
System.exit(1);
}
System.out.println("ConnectionThread constructed.");
connections.add(conn);
System.out.println("ConnectionThread added to queue.");
conn.init();
System.out.println("Finished ConnectionThread initialization, verifying...");
if (conn.isInitialized) {
System.out.println("ConnectionThread Initialized, preparing to start new thread.");
(new Thread(conn)).start();
}
}
}
public static void main(String[] args) {
System.out.println("~~MMO Server Alpha .1~~");
Server server = new Server();
System.out.println("Constructed Server");
server.init();
System.out.println("Server Initialized, preparing to start...");
server.start();
}
}
Here's the ConnectionThread class:
public class ConnectionThread implements Runnable {
boolean shouldBeListening = true;
boolean isThereAnUnsentOutgoingMessage = false;
String outgoingMessage = "OUTGOING UNINITIALIZED";
boolean IsThereAnUnsentIncomingMessage = false;
String incomingMessage = "INCOMING UNITIALIZED";
boolean isInitialized = false;
PrintWriter out;
BufferedReader in;
String currentInputMessage = "Test Input Message from the Server ConnectionThread";
String previousInputMessage = null;
Socket socket;
public ConnectionThread(ServerSocket s) {
System.out.println("ServerSocket passed to ConnectionThread: " + s);
/*
* The purpose of the constructor is to establish a socket
* as soon as possible. All transmissions/logic/anything else
* should happen in init() and/or run().
*/
System.out.println("Constructing ConnectionThread.");
try {
Socket socket = s.accept();
System.out.println(socket);
}
catch (IOException e) {
System.out.println("Error in ConnectionThread constructor");
System.exit(1);
}
}
public void init() {
/*
* Everything should be set up here before run is called.
* Once init is finished, run() should be set to begin work.
* This is to ensure each packet is efficiently processed.
*/
try {
System.out.println("Establishing in and out streams:");
System.out.println(socket);
out = new PrintWriter(socket.getOutputStream(), true);
System.out.println("ConnectionThread: Output Stream (PrintWriter) Established");
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("ConnectionThread: InputStream (BufferedReader) Established");
}
catch (IOException e) {
System.out.println("Error in ConnectionThread method Init.");
System.exit(1);
}
isInitialized = true;
}
And optionally, here's the test client:
public class TestClient {
static PrintWriter out;
BufferedReader in;
public final int PORT = 6969;
Socket socket = null;
InetAddress host = null;
public TestClient() {
out = null;
in = null;
socket = null;
host = null;
}
public void connectToServer() {
System.out.println("Connecting to server...");
try {
host = InetAddress.getLocalHost();
socket = new Socket(host.getHostName(), PORT);
}
catch (Exception e) {
System.out.println("Error establishing host/socket");
System.exit(1);
}
try {
System.out.println("Establishing I/O Streams");
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
catch (Exception e) {
System.out.println("Error establishing in/out streams");
System.exit(1);
}
}
public static void main(String[] args) {
System.out.println("~~TestClient Alpha .1~~");
TestClient c = new TestClient();
c.connectToServer();
System.out.println("Should be connected to server. Sending test message...");
while (true) {
System.out.println("here");
out.println("Hello there");
}
}
}
The 'socket' variable in the constructor of ConnectionThread shouldn't be local. It is shadowing the member variable.
It is customary to call accept() in the listen() loop, and pass the accepted socket to the ConnectionThread.
As EJP said, in your ConnectionThread constructor you think that you are assigning the value to the socket field, however you are actually assigning the value to the socket method variable, thus the socket field remains null, and in init() you see socket as null.
In addition to EJP answer: you did not provide ConnectionThread.run() method, but I assume you are going to use fields in, out and socket in your run() method. Since these fields are not marked as volatile or final, depending on your luck and number of core on your computer, you may also get NullPointerException at run() method.
This is because new variable value may be not propagated between caches and new thread will not see value of changed.
Explanation of this possible problem is here - The code example which can prove "volatile" declare should be used
I am trying to write a program in which the client requests the number of cores the server has. I do this as follows:
Client:
public void actionPerformed(ActionEvent e) {
try {
Socket clientSocket = new Socket("128.59.65.200", 6789);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String numberOfCores = inFromServer.readLine();clientSocket.close();
System.out.println(numberOfCores);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
Server:
public static void sendNumberOfCores() {
Thread coresThread = new Thread() {
public void run() {
try {
int numberOfCores;
ServerSocket welcomeSocket = new ServerSocket(6789);
while (true) {
Socket connectionSocket = welcomeSocket.accept();
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
numberOfCores = Runtime.getRuntime().availableProcessors();
outToClient.write(numberOfCores);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
coresThread.setName("Wait for core request thread");
coresThread.start();
}
However, when I load the server and hit the button on my gui which runs the client code, nothing happens and the button just gets stuck. What is causing this?
Thank you.
Server not initialized on the 6789 port and make sure you do that in a separate thread.
Some thing like this.
In Server class:
--Make an inner class say MyServer
class MyServer implements Runnable{
final int BACKLOG=10; //10 is the backlog,if your server wishes to serve requests.
final int PORT = 6789;
public void run(){
try {
ServerSocket serverSocket = new ServerSocket(PORT,BACKLOG); //10 is the backlog,if your server wishes to serve conncurrent requests.
while (true) {
Socket ClientConnetion = serverSocket.accept();
//Now whatever you want to do with ClientConnection socket you can call
}
} catch (Exception e) {
e.printStackTrace();
}
}
--Start this thread in you main server class
MyServer mys=new MyServer();
Thread r=new Thread(mys);
mys.start();
It ended up that I was sending an integer when the code on the client was waiting for a string.