I am trying to make client-server connection. First I have executed server code in one console and then client code in another console. I want that after the client code runs, the client enters his name and then I will create the object of client socket class and print the name of client in the server console. But on the server console it prints null when I try to print the name of client.
Since accept() method of server class waits for the client socket object, so before this line System.out.println(Myclient1.nameOfClient + " connected"); gets executed, client would already have entered his name in String nameOfClient.
I am unable to understand the reason behind this.
Server code
public Myserver1() {
try {
ss = new ServerSocket(10);
while (true) {
s = ss.accept(); // waits for the client socket
System.out.println(Myclient1.nameOfClient + " connected"); // Here I want to print the name of client(Myclient1.java).
al.add(s);
Runnable r = new MyThread(s, al);
Thread t = new Thread(r);
t.start();
}
} catch(Exception e) {}
}
Client code
public Myclient1() {
System.out.println("enter ur name");
nameOfClient = new Scanner(System.in).nextLine(); // Here I am storing the name of client so that I can access nameOfClient from Myserver1.java
try {
s = new Socket("localhost", 10);
din = new DataInputStream(s.getInputStream());
dout = new DataOutputStream(s.getOutputStream());
clientchat();
} catch(Exception e) {}
}
Server and clients should run independently of each other, or else it defeats the purpose of networking.
Right now, you are accessing a static variable the has never been initalized because the client isnt running in the same process as the server.Send the name over a socket, and use that as your print and your problem will be fixed.
Related
I've learned in Java how to stream data over a network connection using ServerSocket and Socket, such as:
Client.java:
Socket socket = new Socket(address, port);
int i;
while ((i = System.in.read()) != -1)
socket.getOutputStream().write(i);
Server.java:
ServerSocket server = new ServerSocket(port);
Socket socket = server.accept();
int i;
while ((i = socket.getInputStream().read()) != -1)
System.out.println(i);
This would simply have Client blocking on System.in.read() at one end, and Server blocking on socket.getInputStream().read() at the other, and the bytes get passed when ENTER is pressed in the Client program.
How would I accomplish something similar within a single program, without using Sockets? For example, if I had Thread A waiting on keyboard input which is then streamed to Thread B which is able to "consume" the bytes at an arbitrary time in the future, just as Server (above) is able to consume bytes from socket.getInputStream() at some arbitrary time?
Is PipedInput/OutputStream the right solution for this, or ByteArrayInput/OutputStream, or something else? Or am I overthinking it?
Yes, you can use PipedInputStream/PipedOutputStream for "streaming" data "locally" in your JVM. You create one PipedInputStream and one PipedOutputStream instance, connect them with the connect() method and start sending/receiving bytes. Check the following example:
PipedInputStream pipedIn = new PipedInputStream();
PipedOutputStream pipedOut = new PipedOutputStream();
pipedIn.connect(pipedOut);
Thread keyboardReadingThread = new Thread() {
#Override
public void run() {
System.out.println("Enter some data:");
Scanner s = new Scanner(System.in);
String line = s.nextLine();
System.out.println("Entered line: "+line);
byte[] bytes = line.getBytes(StandardCharsets.UTF_8);
try {
pipedOut.write(bytes);
pipedOut.flush();
pipedOut.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Keyboard reading thread terminated");
}
};
keyboardReadingThread.start();
Thread streamReadingThread = new Thread() {
#Override
public void run() {
try {
int bytesRead = 0;
byte[] targetBytes = new byte[100];
System.out.println("Read data from the PipedInputStream instance");
while ((bytesRead = pipedIn.read(targetBytes)) != -1) {
System.out.println("read "+bytesRead+" bytes");
String s = new String(targetBytes, 0, bytesRead, StandardCharsets.UTF_8);
System.out.println("Received string: "+s);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Streaming reading thread terminated");
}
};
streamReadingThread.start();
keyboardReadingThread.join();
streamReadingThread.join();
First the two piped stream instances are connected. After that two threads will read from the keyboard and read from the PipedInputStream instance. When you run your application you will get an output similar to this (with Some example input for testing being the keyboard input):
Enter some data:
Read data from the PipedInputStream instance
Some example input for testing
Entered line: Some example input for testing
Keyboard reading thread terminated
read 30 bytes
Received string: Some example input for testing
Streaming reading thread terminated
Also notice that the threads are not synchronized in any way, so the System.out.println() statements might get executed in a different order.
This is mostly an extension of the answer #VGR gave in the comments.
If the entirety of your "Network" exists within the same, single JVM, then you don't need anything like sockets at all - you can just use Objects and methods.
The entire point of Sockets was to allow the JVM to perform actions outside of itself (typically with another JVM somewhere in the outside world).
So unless you are trying to interact with objects outside of your current JVM, it is as simple as this.
public class ClientServerExample
{
public static void main(String[] args)
{
Server server = new Server();
Client client = new Client();
client.sendMessage("Hello Server", server);
}
static class Server
{
String respond(String input)
{
String output = "";
System.out.println("Server received the following message -- {" + input + "}");
//do something
return output;
}
}
static class Client
{
void sendMessage(String message, Server server)
{
System.out.println("Client is about to send the following message to the server -- {" + message + "}");
String response = server.respond(message);
System.out.println("Client received the following response from the server -- {" + response + "}");
//maybe do stuff with the response
}
}
}
Here is the result from running it.
Client is about to send the following message to the server -- {Hello Server}
Server received the following message -- {Hello Server}
Client received the following response from the server -- {}
Note that server doesn't return anything because I didn't do anything in the server. Replace that comment with some code of your own and you will see the results.
EDIT - to better explain a real world example, where a server will respond to requests in FIFO, here is a modified version of the above example.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
public class ClientServerExample
{
public static void main(String[] args)
{
System.out.println("===========STARTING SYNCHRONOUS COMMUNICATION============");
synchronousCommunication();
System.out.println("===========FINISHED SYNCHRONOUS COMMUNICATION============");
System.out.println("===========STARTING ASYNCHRONOUS COMMUNICATION============");
asynchronousCommunication();
System.out.println("===========FINISHED ASYNCHRONOUS COMMUNICATION============");
}
public static void synchronousCommunication()
{
Server server = new Server();
Client client = new Client();
String response = "";
response = client.sendMessage("Good morning Server!", server).join();
System.out.println("Client received the following response from the server -- {" + response + "}");
response = client.sendMessage("Good evening Server!", server).join();
System.out.println("Client received the following response from the server -- {" + response + "}");
}
public static void asynchronousCommunication()
{
Server server = new Server();
Client client = new Client();
List<CompletableFuture<String>> responses = new ArrayList<>();
responses.add(client.sendMessage("Good morning Server!", server));
responses.add(client.sendMessage("Good evening Server!", server));
for (CompletableFuture<String> eachResponse : responses)
{
System.out.println("Client received the following response from the server -- {" + eachResponse.join() + "}");
}
}
static class Server
{
CompletableFuture<String> respond(final String input)
{
System.out.println("Server received the following message -- {" + input + "}");
return
CompletableFuture.supplyAsync(
() ->
{
try
{
//sleep for 2 seconds, to represent arbitrary delay in receiver processing
Thread.sleep(2000);
return input.contains("morning") ? "Good morning to you too!" : "Good evening to you too!";
}
catch (Exception e)
{
throw new IllegalStateException("What happened?", e);
}
});
}
}
static class Client
{
CompletableFuture<String> sendMessage(String message, Server server)
{
System.out.println("Client is about to send the following message to the server -- {" + message + "}");
return server.respond(message);
}
}
}
Both of these examples are performing a FIFO approach to data processing. They receive the request, calculate a response, and then send back a CompletableFuture, which is basically an Object that contains the response that will arrive once the Server gets around to it, sort of like a Promise in Javascript.
For the synchronous example, we see that a client message is sent, and then processed before the next one is sent. As a result, we have a minor delay between the 2 (about 2 seconds).
For the asynchronous example, we see that both client messages are sent, and their CompletableFutures are put into a batch list, which is converted to normal strings once all requests have been sent.
The synchronous example takes around 10 seconds.
The asynchronous example takes around 5 seconds.
Both of these are different ways of performing FIFO in the way that you described. They both are examples where multiple clients send a request to the server, and then the server finishes them when they get around to it. That 5 seconds delay is meant to represent the idea of "getting around to it". In reality, getting around to it usually means that the server has so much on it's plate that it will take a long time before it has a chance to give a full response.
Let me know if you need another example to better help you understand.
I am new to java server and client. I want to make a multi-client server. After making server code ready to accept more than one client it is like this :
Server code :
public class Server {
int clientNumber = 1;
ServerSocket mServer = new ServerSocket(9090);
try {
while (true) {
new TheServer(mServer.accept(), clientNumber++).start();
}
} finally {
mServer.close();
}
}
private static class TheServer extends Thread {
private Socket client;
private int clientNumber;
public TheServer(Socket client, int clientNumber) {
this.client = client;
this.clientNumber = clientNumber;
}
public void run() {
try {
DataOutputStream dos = new DataOutputStream(client.getOutputStream());
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
dos.writeUTF(numberString);
while (true) {
String message = br.readLine();
dos.writeUTF(message);
}
} catch (IOException e) { }
}
}
The clients are added to the server as I expect.
If I have one client, the --- dos.writeUTF(message); --- give the desired result inside client console, so in server console I write down (A) and press enter, then the (A) is printed inside #1 Client, then I write down (B) in server console and press enter, then the (B) is printed inside #1 Client, it seems good.
But if the second client join the server, the result inside both clients console is hold for one time press and is fired on second enter press. To simplify : Inside server console I press (A) and press enter, nothing is happening on clients consoles, then I press (B) inside server console again, and now the first message (A) and second message (B) are printed one (A) inside #1 Client and one (B) inside #2 Client and this is not the behavior that I expect.
What I expect: When 2 Clients exist and server send message (A), I need all Clients (here there are 2 clients) get the message together. Imagine you are playing a game online, If I have a character (like a ball) and I move it inside a game field, all the other players have to see my character moving. I wish I was clear.
I think I have to make an array to keep the clients and send message to that array maybe...
So how can I solve it. If the client code is needed please tell me.
Look into something called the Publish-Subscribe pattern, also known as the Observer pattern, here is an example:
https://www.journaldev.com/1739/observer-design-pattern-in-java
I am creating a server-chat-client application and have borrowed code. I know how most of the things work except one.
In my Class Server I wait for a socket to be accepted.
public static ArrayList<String> clientUsernameList = new ArrayList<>();
/**
* #param args the command line arguments
* #throws java.io.IOException
*/
public static void main(String[] args) throws IOException {
int port = 8900; //Port number the ServerSocket is going to use
ServerSocket myServerSocket = null; //Serversocket for sockets to connect
Socket clientSocket = null; //Listerner for accepted clients
ClientThread[] clientsConnected = new ClientThread[20]; //Max clients in this server
try {
myServerSocket = new ServerSocket(port);
System.out.println("Server waiting for clients on port:" + port);
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
while (true) {
try { //Freezes while-loop untill a socket have been accepted or if some failure occur
clientSocket = myServerSocket.accept();
System.out.println("Client have connected from:" + clientSocket.getLocalAddress().getHostName());
} catch (Exception e) {
//Print out exception
System.out.println(e);
}
//For-loop that counts every element in Array-clientsConnected
for (int i = 0; i < clientsConnected.length; i++) {
//If-statement checks if current element is null
if(clientsConnected[i] == null){
//If current element in the Array is null then create a new object from ClientThread class
//With a socket and the object of itself as parameter.
(clientsConnected[i] = new ClientThread(clientSocket, clientsConnected)).start();
//Must have a break otherwise it will create 20 objects (Exit for-loop)
break;
} //Exit if-statement
} //Exit for-loop
} //Exit while-loop
}
}
So if a socket gets accepted I create a thread class called Class ClientThread
To create a object of this class I need a socket and a array.
This is how my ClientThread class looks like
public class ClientThread extends Thread {
private ClientThread[] clientsConnected;
private Socket SOCKET = null;
private DataInputStream IN = null;
private DataOutputStream OUT = null;
private String userName,zone;
//-------------------------------------------------------
//Constructor
public ClientThread(Socket socket, ClientThread[] clientThread) {
this.SOCKET = socket;
this.clientsConnected = clientThread;
}
//Some more code
Now this is where I am lost. Do I send in my whole array? and if I do shouldn't user1 only get an array with 1 user and when user2 connects shouldn't he get an array with 2 users? I am lost. If someone could point me to something that explains this I would be grateful.
Your code will serve only 20 requests. For each one it adds new value to clientsContected, once the whole table is full it will just go back to the start of the loop (without closing the accepted connection).
Probably the idea of passing the clientsConnected to the thread, was so it can set the value to null once it stopped working (so that your main code in the loop can assigne a new client to it). GUessin as no code is included). But for that an index inside the array would be useful (so 3 parameters instead of 2) so the ClientThread doesn't have to search the whole array to find object matching this.
I would rather recommend using BlockingQueue (with limited capacity for example 5) to which you will pass accepted connections. Once it is full your main will be forced to wait on it till it has same space to insert new connection so you will stop accepting new sockets. Create the 20 threads, that in a inifinite loop tries to get a socket from that queue and serve it. Once they finish they go back an wait for new request.
So yes you passs the whole array.
Still it doesn't solve the problem of what happens if all are busy, as you keep accepting new clients instead of waiting for free Thread.
I have a simple echo server, and I want when a connected user types anything to the server, all other clients and that client will get a the message + " | MOD".
It wont send to all clients now but it should and I just don't know what's wrong in my code, so now it will just send the message + " | MOD" to the client who sent the message but not to all others also as it should.
I just don't get it, I have a loop that goes through all clients, but it still won't send to all.
SERVER:
package com.murplyx.server;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class Server {
public static ServerSocket server;
public static ArrayList<Socket> clients = new ArrayList<Socket>();
public static void broadcast(String message) {
try {
for (Socket socket : clients) {
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.println(message);
}
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
try {
server = new ServerSocket(9000);
while (true) {
clients.add(server.accept());
for (Socket socket : clients) {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = in.readLine();
if (line != null) {
broadcast(line + " | MOD");
}
}
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
CLIENT:
package com.murplyx.client;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class Client {
public static void main(String args[]) {
try {
while (true) {
Socket socket = new Socket("localhost", 9000);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
out.println(input.readLine());
System.out.println(in.readLine());
socket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Please help.
Thanks alot.
One of the issues you have is that each client will repeatedly do read stdin, write socket, read socket, write stdout, ... ad infinitum.
When you broadcast all other clients are still typically sat in the read stdin phase, so they don't know that there's stuff waiting to be read on the socket. They're still waiting for the user to enter something.
One of the simplest options is to start two threads in each client - one just handles read stdin, write socket, ... and the other handles read socket, write stdout.
[Another (potentially more sophisticated) option us to use Java NIO to poll both the socket and stdin for available input at the same time].
A second issue is that you're blocking in the accept call in the server, and then reading from each socket in turn. You might accept in one thread, and have another thread per client read from just the client, and rebroadcast to the others. NIO can also be a good option here - you can poll for reads any any client.
I'm not exactly sure how ArrayLists play with sockets, so I definitely would go back to using a normal array for it (see the edited code here Java EchoTCPServer - Send to all clients)
Some things I see that I think can to be fixed:
On the Client:
-Stop closing the socket in the While loop. Close it OUTSIDE the while loop (When the client is done with the server). Also, declare the socket outside the Loop.
NOTE ON THIS: When a client makes a socket to connect to the server, it is automatically given a device port, so two different devices will never have the same IP connected to the server. A TCP connection consists of 2 ports, server socket and client socket, and the sockets are denoted by [deviceip:port,serverip:port] (iirc).
-Also, on the client you don't need to declare a new reader everytime you move through the while loop. Put that all outside. The only thing inside the while loop should be your readline + print statements.
-readLine is a blocking method. (just in case you don't know what that means, it means that readLine will make your program be stuck there until the it actually reads a line. To bypass this, you can use an if statement combined with the .ready() function. The ready function checks to see if there is anything to be "read in", so if there's no input it wont be stuck on "readLine".
On the Server:
-Like i said earlier, I'd change back to using a normal Array.
-Your server will still get stuck on .accept(). As such, you will never be able to read input from the clients except once after each connection. You can use a thread to listen instead, and it will still work.
eg: (this code goes with the code that's in the link i attached (also your question), put it before the while loop of your server)
// create a tcp listener thread to deal with listening to clients
Thread listenerThread = new Thread() {
public void run() {
String clientSentence;
while (true) {
//loop through each connected socket
for (int i = 0; i <= intLastSocket; i++) {
Socket z = clientSocket[i];
//make sure the socket is not null or closed (can't do anything
//with closed or null sockets
if ((z != null) && (!z.isClosed())) {
try {
// Deal with TCP input here
BufferedReader input = new BufferedReader(new
InputStreamReader(z.getInputStream()));
// read in a line but only if there is one
if (input.ready()) {
clientSentence = input.readLine();
}
} catch (IOException x) {
printTCP("IOException caught when reading in: "
+ x.toString());
}
if (clientSentence != null) {
System.out.println("Received from client: "
+ clientSentence);
//send this message to the client
outputStream[i].println(clientSentence + " | MOD");
}
// clear the input
clientSentence = null;
}
}
}
}
};
listenerThread.start();
I tried to make a console chat server. the main problem i am facing is that i can not send the message to the server.. as you can see in the img i uploaded that the server and the client are connected. but when i type anything in the client side. The client becomes unresponsive and i have to close the cmd prompt.
How can i fix this?
Is something wrong with my computer or is the code wrong?
public class MyClient
{
Socket s ;
DataInputStream din ;
DataOutputStream dout;
public MyClient()
{
try
{
s= new Socket("localhost",10);
System.out.println(s);
din = new DataInputStream(s.getInputStream());
dout= new DataOutputStream(s.getOutputStream());
ClientChat();
}
catch(Exception e)
{
System.err.println(e);
}
}
public void ClientChat() throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//Scanner s2 = new Scanner(System.in);
String s1;
System.out.println("start the conversation");
do
{
s1=br.readLine();
//s1=s2.nextLine();
dout.flush();
System.out.println("server:"+din.readUTF());
}
while(!s1.equals("stop"));
}
public static void main (String args[])
{
new MyClient();
}
}
The code snippet never calls dout.write*(), so nothing is ever sent over the Socket.
readLine() will block until a line of text is read, so messages sent to the client won't be printed until after the client types a 2nd line of text. You can fix this either by using asynchronous I/O or by moving the read loop into it's own Thread.
You need to make the server and client a thread, so they can work independently.
server as thread will wait for a client connections and will receive messages.
client as thread will work on its own.
problem is that they cannot run concurrently.
Use dout.writeUTF(s1); inside the do loop.
The writeUTF will allow you to write the subsequent message till then It will be stuck at readutf function.
The java.io.DataOuputStream.writeUTF(String str) method writes a string to the underlying output stream using modified UTF-8 encoding. Refer to this