I am currently developing a client-server application and I have this problem: I want to create a different class instance depending on what the connected socket sends, but it only creates the first instance then it stucks. Here is some piece of code:
Socket clientSocket = null;
ServerSocket server = null;
String buff = null;
transfer tr = null;
colectieClienti clienti = new colectieClienti();
And:
while (true) {
try {
clientSocket = server.accept();
buff = (new BufferedReader(new InputStreamReader(clientSocket.getInputStream()))).readLine();
if (buff.equals("client")) {
(colectieClienti.useri[colectieClienti.nrUseri++] = new clientThread(clientSocket, stmt)).start();
} else {
tr = new transfer(clientSocket);
tr.start();
}
} catch (IOException ex) {
System.out.println(ex);
}
}
I have to mention that clientThread is a class that extends Thread and communicates with a GUI, and transfer is a class that only send some files from client to server. The logic is something like this: In the GUI the user connects to the server, so it is created a new instance of clientThread and after this, when the user press a button it creates a new socket (on the client side and send a message to the server, something like "I want to create a new instance of transfer class, which is done by the buff) and receive the data. But it only creates the clientThread instance and then it stucks. Can anyone help me?
LE: This is the constructor of clientThread
public clientThread(Socket socket, Statement statement) {
comunicare = socket;
try {
oStream = comunicare.getOutputStream();
is = new BufferedReader(new InputStreamReader(comunicare.getInputStream()));
os = new PrintStream(oStream);
} catch (IOException ex) {
System.out.println(ex);
}
this.statement = statement;
}
This is only a guess, but are you sending a line terminator from the client? BufferedReader.readLine() reads until it gets a \n, \r, or a \r\n, so if the client is not writing that, the server will just wait.
First and foremost: avoid extending the thread class and opt out for implementing a runnable.
But it only creates the clientThread instance and then it stucks. Can anyone help me?
Then show us what you do when you create the clientThread, showing us what you do on the server (alone) is not enough for us to tell you what you're doing wrong.
Related
I have two classes server and client. I am running both the server and the client on the intelliji. I am able to write the data to the Json file on the server but when it comes to reading the data, I am not able to read it. My application is not responding when I am trying to read the data. I am new to Socket Programming please help me.
Here is the code on the client side
import java.io.*;
import java.net.Socket;
public class Client {
public String readDataFromServer(Socket socket) throws IOException {
InputStreamReader inputStreamReader = new
InputStreamReader(socket.getInputStream());
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
return bufferedReader.readLine();
}
public void writeDataToServer(String obj) throws IOException {
Socket socket = new Socket("localhost", 1299);
OutputStreamWriter outputStreamWriter = new
OutputStreamWriter(socket.getOutputStream());
PrintWriter printWriter = new PrintWriter(outputStreamWriter);
printWriter.write(obj);
printWriter.flush();
printWriter.close();
}
}
Here is the code on the server side
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
static void writeJson (String str) throws IOException {
FileWriter pw = null;
try {
pw = new FileWriter("MYJSON.json", true);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
pw.write(str + '\n');
pw.flush();
try {
} catch (Exception E) {
E.printStackTrace();
}
pw.close();
}
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(1299);
Socket socket = serverSocket.accept();
InputStreamReader inputStreamReader = new InputStreamReader(socket.getInputStream());
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = bufferedReader.readLine();
writeJson(str);
FileReader fileReader = new FileReader("MYJSON.json");
BufferedReader buff = new BufferedReader(fileReader);
OutputStreamWriter outputStreamWriter = new
OutputStreamWriter(socket.getOutputStream());
PrintWriter printWriter = new PrintWriter(outputStreamWriter);
printWriter.write(buff.readLine());
printWriter.flush();
}
}
I have another class called display controller which is calling the method which is calling the method by passing the socket object. Here is the piece of code from this class.
Client client = new Client();
button1.setOnAction(e-> {
try {
String str;
while ((str = client.readDataFromServer(socket)) != null) {
Object obj = null;
try {
obj = jsonParser.parse(str);
What I am doing wrong here? How do I fix it?
Thank you
There's a couple of issues in your code.
The main one is in the main method of the Server class. Your server only accepts one connection. That connection writes and reads the json file and then your main method ends. If your main program ends, then the server is gone. This means that the first client that connects will work and write to the file, but any subsequent connections will not connect because there's no server accepting connections anymore. Typical servers run indefinitely by using a while loop with true as the condition.
Example Structure of a server without threads:
public class Server {
// this class represents an instance of a client connection to this server
// It's an object that keeps track of the socket created by referencing
// the connection.
private class ClientInstanceOnTheServer {
private Socket connectionToClient;
public ClientInstanceOnTheServer(Socket connectionToClient) {
this.connectionToClient = connectionToClient;
}
private void logicToServeAClient() {
// here goes the logic that serves a client
}
public void run () {
try {
logicToServeAClient();
} finally {
try {
socket.close();
} catch (IOException e) {// handle exceptions!}
}
}
}
public static void main(String [] args) {
try {
ServerSocket serverSocket = new ServerSocket(1299);
while (true) { // run indefinitely
Socket socket = serverSocket.accept(); // accept connections from clients
// keep track of the socket object as it represents a connection to a client
// the server is responsible for keeping track of its connections to clients
// Example:
ClientInstanceOnTheServer client = new ClientInstanceOnTheServer(socket);
client.run();
}
} finally {
serverSocket.close();
}
}
}
Example Structure of a server with Threads:
NOTE: The code below is not to represent a complete solution with threads, but rather an example to explain how a server works.
public class Server {
// this class represents an instance of a client connection to this server
// It's an object that keeps track of the socket created by
// the connection and it runs in a separate thread to not block
// the main method thread on this server.
private class ClientInstanceOnTheServer extends Thread {
private Socket connectionToClient;
public ClientInstanceOnTheServer(Socket connectionToClient) {
this.connectionToClient = connectionToClient;
}
private void logicToServeAClient() {
// here goes the logic that serves a client
}
public void run () {
try {
logicToServeAClient();
} finally {
try {
socket.close();
} catch (IOException e) {// handle exceptions!}
}
}
}
public static void main(String [] args) {
try {
ServerSocket serverSocket = new ServerSocket(1299);
while (true) { // run indefinitely
Socket socket = serverSocket.accept(); // accept connections from clients
// keep track of the socket object as it represents a connection to a client
// the server is responsible for keeping track of its connections to clients
// and it should use a separate thread for each client to not block the main method thread.
// Example:
ClientInstanceOnTheServer client = new ClientInstanceOnTheServer(socket);
client.start(); // this will execute the run method in ClientInstanceOnTheServer class.
}
} finally {
serverSocket.close();
}
}
}
Your server is always doing both, writing and reading the json file, regardless of what the client wants. The server should somehow allow the client to communicate what it wants to do, and then it executes only what the client asked for. If we use the skeleton code above, this logic would go in the method logicToServeAClient of the ClientInstanceOnTheServer class. The server and client use the socket object's input and output streams to communicate with each other. The server and client need to agree beforehand on which commands/operations the client needs and the server is willing to serve. In your case, it would be READ and WRITE. Then you create a contract (Protocol) between the client and server on how to send these commands to the server and how the server will respond to the client for each command.
Example of a protocol:
// client sends READ to server
// client waits for respond from server
// server read json file and send it to the client
// client sends WRITE to server
// server then waits for the client to send the string to write.
// Once it receives the string, it writes it to the json file.
All of this is achievable using the socket's input and output streams
It's important to distinguish the difference between the Client and the ClientInstanceOnTheServer classes. Client is your Client class that connects to the server and ClientInstanceOnTheServer holds the connection and also runs the server code that serves the commands requested by the Client class. In the protocol above, whenever client is mentioned, is referring to the Client class. Whenever the server is mentioned is referring to the ClientInstanceOnTheServer class.
You can find more examples on google, like: http://cs.lmu.edu/~ray/notes/javanetexamples/. However, this should set you up on a path to fix your issue.
Cheers
We created a server client relation between java (eclipse on windows/server) and android app (android studio/client). The communication seems fine, but sometimes the connecting is horrably slow, up to the point where the app and and server don't respond anymore. Yet, no real error is given and there is no pattern to when the connection goes well or when it is slow.
We looked for answers here at stack, but we could only find answers regarding the output and input streams. However, once the connection (serverSocket.accept()) is made, the program runs fine and the streams are created super fast. Thus we think the problem lies with the server side creation of sockets. The program only has to handle a maximum of 30 clients, and the only communication exists of strings (so no enormous data transfers).
Note: when one connection acceptation is slow, the next upcomming requests from clients have to wait. When it's their turn they are again randomely fast or slowly accepted by the server. All connections are made on port 8080.
The code of our server and client are given below, does anybody know why the connection is (at some random times) so slow?
SERVER:
public void run() {
keepGoing = true;
try {
serverSocket = new ServerSocket(port);
while (keepGoing) {
display("Server waiting for Clients on port " + port + ".");
Socket socket = serverSocket.accept(); //<---our problem
if (!keepGoing) break;
ClientThread t = new ClientThread(socket, this); //<---program doesnt reach this code when it is slow. One client thread exists for each connection.
}catch (IOException e) {
String msg = sdf.format(new Date())
+ " Exception on new ServerSocket: " + e + "\n";
display(msg);
}
}
CLIENT THREAD CODE: (not reached if slow)
public ClientThread(Socket socket, Server s) {
this.server = s;
this.socket = socket;
System.out.println("Thread trying to create Object Input/Output Streams");
try {
// make streams
sOutput = new ObjectOutputStream(socket.getOutputStream());
sInput = new ObjectInputStream(socket.getInputStream());
// read user account info
String input = (String) sInput.readObject();
String[] accountInfo = input.split(";");
username = accountInfo[0];
password = accountInfo[1];
} "catch all problems"
}
CLIENT (android)
Thread connect = new Thread(new Runnable() {
#Override
public void run()
{
try
{
socket = new Socket(ip.getText().toString(), portNr);
sOutput = new ObjectOutputStream(socket.getOutputStream());
sInput = new ObjectInputStream(socket.getInputStream());
}
catch (UnknownHostException e ){
e.printStackTrace();
} catch(IOException e ){
e.printStackTrace();
}
"sending account information"
}
});
connect.start();
try {
connect.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
Thanks so much!
You should make the streams in the ClientThread in the run() method, before you start looping. Not in the constructor. Otherwise you are doing I/O in the accept thread, which slows it down.
I have no idea why you're creating a thread in the client only to join it immediately.
You should extract your main server loop (while(keepGoing)...) into a run method and make the server implement the Runnabel interface. Then create a new Thread and start it.
Example:
public class Server implements Runnable{
private Thread thread;
public Server(){
thread = new Thread(this);
thread.start(); //I would create start() and stop() methods but for simplicity I just use thread.start()
}
#Override
public void run(){
//while....
}
}
I hope you get what I want to say, otherwise just comment and I will upgrade my example ;)
Turns out we had a router issue. When connecting all tablets and computer to a local hotspot it ran super smooth! Tanks everyone for the help :D
EDIT: Try a BufferedStreamReader mentioned here: Java socket performance bottleneck: where?
Instead of:
sOutput = new ObjectOutputStream(socket.getOutputStream());
Use:
sOutput = new ObjectOutputStream(new BufferedOutputStream(socket.getOutputStream()));
and flush it with:
sOutput.flush();
Same goes for the InputStream, use BufferedInputStream.
I am trying to create a multiclient chat sort of server in which we have multiple clients connecting to server and whatever message a client enters, it gets displayed to all the clients(including the client who sent the message). I am not getting this output, instead the message just echoes only on the sender client and no other client. Code is quite long, hence i am displaying snippets of whichever code i think will help you understand error. In case, it is not enough, just comment which part you require. Thanks in advance. I am stuck on this since about hour and half, so i appreciate whatever help i would get.
The Server Class
public class Multiserver {
ServerSocket serversocket;
Socket socket;
ArrayList<Socket> al = new ArrayList<Socket>();
DataInputStream dis;
DataOutputStream dos;
Multiserver() throws IOException
{
serversocket = new ServerSocket(1036);
System.out.println("Server started on port 1036");
while(true)
{
socket = serversocket.accept();
System.out.println(socket);
al.add(socket);
Mythread thread = new Mythread(socket, al);
thread.start();
}
}
Thread used in server class
public class Mythread extends Thread{
Socket socket;
ArrayList al;
DataInputStream dis;
DataOutputStream dos;
Mythread(Socket socket, ArrayList al)
{
this.socket = socket;
this.al = al;}
public void run()
{
try{
String data ="";
dis = new DataInputStream(socket.getInputStream());
data = dis.readUTF();
if(!data.equals("stop"))
{
broadcast(data);
}
else
{
dos = new DataOutputStream(socket.getOutputStream());
// data = dos.readUTF();
dos.writeUTF(data);
dos.flush();
//dos.close();
}
}
catch(Exception e){
System.out.println("Run "+e);
}
}
public void broadcast(String data)
{
try{
Iterator it = al.iterator();
while(it.hasNext())
{
Socket socket1 = (Socket)it.next();
dos = new DataOutputStream(socket1.getOutputStream());
dos.writeUTF(data);
dos.flush();
}
}
catch(Exception e){
System.out.println("Broadcast running "+ e);
}
}
}
The client class
public class Multiclient {
Socket socket;
DataInputStream dis;
DataOutputStream dos;
Multiclient() throws IOException
{
socket = new Socket("127.0.0.1", 1036);
System.out.println(socket);
Mythreadc my = new Mythreadc(socket);
my.start();
}
Thread used in client class
public class Mythreadc extends Thread{
DataInputStream dis;
DataOutputStream dos;
Socket socket;
Mythreadc(Socket socket)throws IOException
{
this.socket = socket;}
public void run()
{
BufferedReader br = null;
try{
br = new BufferedReader(new InputStreamReader (System.in));
dos = new DataOutputStream(socket.getOutputStream());
String data = "";
do{
data = br.readLine();
dos.writeUTF(data);
System.out.println(data);
dos.flush();
}
while(!data.equals("stop"));
}
catch(Exception e)
{
System.out.println("Client input "+e);
}
finally{
try{
br.close();
dis.close();
dos.close();
}
catch(Exception e)
{
System.out.println("Closing "+e);
}
}
}
}
I am sorry i have put on such a long code, almost all the program. But i feel it is necessary to understand where the problem lies.I have tried and i think it lies in the part where we display data written in the client's socket in the client thread class but i don't know what it is ???
#EDIT: Forgot to mention. The client stops when he sends the message "Stop"!
There are two problems with your code that are preventing the clients from displaying more than one message.
Problem one: Your client code never actually displays or prints out the messages it receives from the server. The line
dos = new DataOutputStream(socket.getOutputStream());
creates an OutputStream you can use to write data to the socket, i.e. send messages to the server. But you never use the socket's InputStream, which is what you need to do to read data from the socket, i.e. receive messages from the server. When you see a message printed out on the client, you're actually just seeing the result of
System.out.println(data);
which has your client print the message it just sent.
In order for the client to accept input from the user and read messages from the server at the same time, you should probably use two threads on the client. One thread can just be the client thread you already wrote, since it takes care of accepting input from the user. The other thread should look something like this:
public class ClientReaderThread extends Thread {
Socket socket;
ClientReaderThread(Socket socket) {
this.socket = socket;
}
public void run() {
try (BufferedReader serverReader = new BufferedReader(
new InputStreamReader(socket.getInputStream()))){
String fromServer = serverReader.readLine();;
while(fromServer != null) {
if (fromServer.equals("stop"))
break;
System.out.println(fromServer);
fromServer = serverReader.readLine();
}
} catch (IOException e) {
System.out.println("Client error! Got exception: " + e);
}
}
}
(Note that I use the try-with-resources statement to construct the reader, which takes care of closing it when the client stops).
Then in your main client class, start both threads with the same socket:
Multiclient() throws IOException
{
socket = new Socket("127.0.0.1", 1036);
System.out.println(socket);
Mythreadc my = new Mythreadc(socket);
ClientReaderThread reader = new ClientReaderThread(socket);
my.start();
reader.start();
}
Problem two: Your server only reads and echoes a single line from each client, because the socket thread that handles each client (Mythread) doesn't contain a loop. With your setup of creating a single thread per client, run() only gets called once per client, so that run() method needs to handle every message that client sends.
Here's how the run() method in the server's thread should look:
public void run() {
try (BufferedReader inStream = new BufferedReader(
new InputStreamReader(socket.getInputStream()))){
String data = inStream.readLine();
while(data != null) {
if(data.equals("stop"))
break;
broadcast(data);
data = inStream.readLine();
}
}
catch(Exception e){
System.out.println("Run exception "+e);
} finally {
al.remove(socket); //This is important to do
}
}
I made an additional important change here: at the end of the run() method, when either the client disconnected or an exception happened, the thread removes its socket from the ArrayList. This ensures that other server threads, which all reference the same ArrayList, don't try to broadcast to the socket of a client that has disconnected. If you neglect to do this, you'll get an exception when a client sends a message to the server after another client has disconnected.
Miscellaneous notes
As I mentioned in my comment, you should give al a type of ArrayList<Socket> inside the thread class, and use a for-each loop instead of an Iterator to iterate over it in broadcast().
I'm using BufferedReader instead of DataInputStream to read from the socket. That's because DataInputStream.readUTF() and writeUTF() are deprecated, and have been replaced with BufferedReader.readLine() and PrintWriter.println().
The streams like dis and dos don't need to be instance variables in your thread classes, since they are only ever used inside the run() method. They can be local variables inside run(), like I did with inStream in my new run() method.
I think you just missed passing the ArrayList of Sockets Users Currently Connected to The Server to the thread
and Instead of Posting your Server Class You have just posted Client Program 2 times anyway ,
Your ServerClass should be build in this way : -
As soon as ServerClass recieves the request from any client, Server Class should add the Socket into ArrayList and create New Thread and just pass both to the MyThread Class
Edit :
It seems you haven't written code for Displaying the data you will get from the server .
At Client Side for Sending the Message You can simple write that in Main Thread that is under Your Client Class's Main Mehtod
You actually needed Thread at client side not for sending the message but rather for Listening the Message from the server,
because you never known when anyone can send you the message but you will always know when you want to send message to anybody connected to this chat App
Now coming to the Coding Part :
Client Class
public class Multiclient {
Socket socket;
DataInputStream dis;
DataOutputStream dos;
Multiclient() throws IOException
{
socket = new Socket("127.0.0.1", 1036);
System.out.println(socket);
Mythreadc my = new Mythreadc(socket);
my.start();
/**
* Here write out the code for taking input from Standard Console
*/
BufferedReader br = null;
try{
br = new BufferedReader(new InputStreamReader (System.in));
dos = new DataOutputStream(socket.getOutputStream());
String data = "";
do{
data = br.readLine();
dos.writeUTF(data);
System.out.println(data);
dos.flush();
}
while(!data.equals("stop"));
}
catch(Exception e)
{
System.out.println("Client input "+e);
}
}
Client Thread
try{
String data ="";
dis = new DataInputStream(socket.getInputStream());
while(data.equalsIgnorCase("stop")){
data = dis.readUTF();
System.out.println("Server Message : "+data);
}
}
catch(Exception e){
System.out.println("Run "+e);
}
Client Thread is not complete but i think this information is sufficient enough .
Hope It help you out , Your problem do remind me of College Days :)
I'm trying to implement a simple server(java application) and client(android app), where the client sends a string about 10 times a second. Everything works fine for a minute or so, after which the server stops receiving messages from the client. Relevant code below.
ClientThread.java
public class ClientThread implements Runnable{
static Socket socket;
static String message = "";
InetAddress serverAddr;
BufferedOutputStream bos;
public ClientThread(String message){
ClientThread.message = message;
}
#Override
public void run() {
try{
serverAddr = InetAddress.getByName(SERVER_IP);
if(socket != null && socket.isConnected())socket.close();
socket = new Socket(serverAddr, SERVER_PORT);
bos = new BufferedOutputStream (socket.getOutputStream());
OutputStreamWriter osw = new OutputStreamWriter(bos, "US-ASCII");
osw.write(message);
osw.flush();
socket.shutdownOutput();
socket.close();
}catch (Exception e) {
}
}
}
ServerThread.java
public class ServerThread extends Thread{
private ServerSocket serverSocket;
static String clientSentence;
public ServerThread(int port) throws IOException, AWTException{
serverSocket = new ServerSocket(port);
}
public void run() {
while(true){
try{
Socket server = serverSocket.accept();
BufferedReader d = new BufferedReader(new InputStreamReader(server.getInputStream()));
clientSentence = d.readLine();
System.out.println(clientSentence);
server.close();
}catch(IOException e){
e.printStackTrace();
break;
}
}
}
}
ClientThread.java is called about 10 times a second using:
Thread clientThread = new Thread(new ClientThread(message));
clientThread.start();
ServerThread.java is initialized and started using:
t = new ServerThread(8888);
t.start();
Any thoughts on why this would freeze after running for a bit? The only way to fix it is to restart the server, after which the same problem happens again after a minute. I spent a lot of time researching this issue but was unable to find a solution.
EDIT: I figured out the server freezes at the clientSentence = d.readLine(); part. Any idea why?
60 connection per second, one minute running: 3600 connections per minute.
Closing a socket doesn't release immediately the associated file descriptor. You may run out of resource at OS layer.
Try to run netstat on server side to see the active, pending and closed connections.
You may read this post on SU.
Your thread never exits and you keep creating new ones. So you run out of something: thread space, sockets, FDs, ...
This is all wrong. Either your thread should loop or you should create a new one. Not both.
Also:
You should use a single connection, not a new one per message.
You are reading lines but to sending them, unless the data already contains a newline, which it shouldn't.
There's a million examples on using Java sockets out there - and every one is the same!
Every one shows a client socket being created, some text being sent, and the socket closed.
I am writing some test code. I want my client to loop round and send quite a few messages. It seems silly to close the client socket each time and re-create, so I thought I would just create one client socket, loop round and send data on the same socket. The thing is though - my server socket does not print out what it has received until the last message has been sent by the client and the client socket closed.
Server:
Socket sock;
ClientConnection client;
ServerSocket ss = new ServerSocket(portNumber);
ss.setSoTimeout(0); // 0=infinite
while (true) {
sock = ss.accept();
client = new ClientConnection(sock);
new Thread(client).start();
// ClientConnection reads from sock, prints, and closes sock
}
ClientConnection (a separate class on the Server side):
public class ClientConnection implements Runnable
{
private Socket m_socket;
private BufferedReader m_in = null;
public ClientConnection(Socket socket)
{
m_socket = socket;
try {
InputStream inStream = socket.getInputStream();
m_in = new BufferedReader(new InputStreamReader(inStream));
}
catch (IOException ioe) {
ioe.printStackTrace();
}
}
public String getMessage()
{
String line = null;
StringBuffer completeMessage = new StringBuffer();
try {
while ((line = m_in.readLine()) != null)
{
completeMessage.append(line);
}
}
catch (IOException ioe) {
ioe.printStackTrace();
return "";
}
return completeMessage.toString();
}
public void run()
{
try {
String message = getMessage();
System.out.println("Received: " +message);
}
finally
{
try {
m_socket.close();
}
catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
}
Client:
socket = new java.net.Socket(m_destination, m_portNumber);
outputStream = socket.getOutputStream();
printStream = new java.io.PrintStream(outputStream);
while (more-stuff-to-send)
{
printStream.print(text);
printStream.print("\n");
printStream.flush();
}
prinStream.close();
socket.close();
ClientConnection is created by the server when I start the client, but it does not print what has been sent until the client is done sending.
I feel like I'm missing the point somewhere along the line. Chat examples are quite common, so if I had a chat client then every message it wanted to send to a chat server it would create a client socket, send the message, and close the socket? Just doesn't seem right somehow.
Thank you.
client = new ClientConnection(sock);
You are passing the socket in constructor.
so you shouldn't do:
socket = new java.net.Socket(m_destination, m_portNumber);
just cache that vatiable from contructor as : this.sock = sock;
getting the reader and the writer is ok, also the server is ok.
I would use a Vector to be synchromized queue for sending messages, and the while (more-stuff-to-send) loop would check the queue and id empty than sleep, if has something to send, than pop the first and sent it while he must do stuff, or socket is closed my the client.