Here is my code for the server side:
#Override
public void run(){
String message;
String command;
String[] arguments;
try{
BufferedReader inStream = new BufferedReader(
new InputStreamReader(
clientSocket.getInputStream()));
while(online){
message = inStream.readLine();
if(message == null)
continue;
if(message.charAt(0) == '/'){
int endOfCommandIndex = message.indexOf(' ');
command = message.substring(1, endOfCommandIndex);
arguments = message.substring(endOfCommandIndex + 1).split(" ");
if(command.equals("login")){
setUserName(arguments[0]);
setName(arguments[0]);
sendMessage(this, "Connected");
}
//....
}
}
}
As mentioned in the title, the thread gets stuck reading from the InputStream of the Socket (I checked with JDB and it's not a conditional waiting because it appears to be still "running").
I tried to write a line to the socket but it doesn't change its state at all. I'm trying to build a chat-like local application and I'm quite new to socket and streams. Thanks in advance.
For the client side:
String msg;
try{
while(!((msg = stdIn.readLine()).equals("/quit")))
toServer.println(msg);
}
catch(IOException e){
e.printStackTrace();
}
In case someone wants review my entire code, it is here hosted on github
It looks like the message is never flushed after being written into the socket stream.
Try either call:
toServer.flush();
after println, or enable auto flushing when constructing toServer:
toServer = new PrintWriter(socket.getOutputStream(), true);
Related
I've been making a chat room where multiple clients can connect and talk together on the same server. The only problem I'm having is getting each client to send more than one message. I've been trying different ways of looping the method to do so but I'm having some issues.
Any help would be appreciated :) thank you.
HERE'S THE CODE:
public class Client {
public static void main(String[] args){
Scanner clientInput = new Scanner(System.in);
try {
Socket SOCK = new Socket("localhost", 14001);
System.out.println("Client started!");
//Streams
while(true){
OutputStream OUT = SOCK.getOutputStream(); //writing data to a destination
PrintWriter WRITE = new PrintWriter(OUT); // PrintWriter prints formatted representations of objects to a text-output stream
InputStream in = SOCK.getInputStream(); //reads data from a source
BufferedReader READ = new BufferedReader(new InputStreamReader(in));
//---------------------------------
System.out.print("My input: ");
String atServer = clientInput.nextLine();
WRITE.write(atServer + "\n");
WRITE.flush(); //flushes the stream
String stream = null;
while((stream = READ.readLine()) != null){ //if stream is not empty
System.out.println("Client said: " + stream);
}
READ.close();
WRITE.close();
}
} catch (UnknownHostException e){
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
I've tried using a while loop to continuously ask for an input but doesn't seem to be working.
Are you making it out of the READ.readLine() while loop? Perhaps you're never getting an end of input character and thats never terminating. Also, you're closing both your READ and WRITE at the end of the while loop, and then expect them to be open on the next iteration. Move those and the close statements to the same layer as the Socket.
With that, every time you send something, your client is expecting something in response from the server. If you don't want them to be dependent on each other, I recommend moving the receive logic to its own thread in a while(true) loop.
I am attempting stream data over a socket with Java in an attempt to write a Kafka producer. I've written a class to pull the data in but I'm not getting the results I'd expect. I've got it set up so the data is being streamed from a Linux box. The source of the data is a csv file that I'm using the nc utility to stream. The class is running on a Windows 10 machine from Eclipse. When I run the class I see two weird things.
The column headers don't get transmitted.
I can only run the class once. If I want to run it again, I have to stop nc and restart it.
Below is my code. Am I missing anything? At this point I'm just trying to connect to the socket and pull the data over.
I run nc with the following command:
$ nc -kl 9999 < uber_data.csv
Below is my class
import java.net.*;
import java.io.*;
public class Client
{
static String userInput;
public static void main(String [] args)
{
try
{
InetAddress serverAddress = InetAddress.getByName("servername");
Socket socket = new Socket(serverAddress, 9999);
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while ((userInput = input.readLine()) != null) {
System.out.println(input.readLine());
}
input.close();
socket.close();
}
catch(UnknownHostException e1)
{
System.out.println("Unknown host exception " + e1.toString());
}
catch(IOException e2)
{
System.out.println("IOException " + e2.toString());
}
catch(IllegalArgumentException e3)
{
System.out.println("Illegal Argument Exception " + e3.toString());
}
catch(Exception e4)
{
System.out.println("Other exceptions " + e4.toString());
}
}
}
You're throwing away every odd-numbered line. It should be:
while ((userInput = input.readLine()) != null) {
System.out.println(userInput);
}
Secondly, you aren't closing the socket. Use a try-with-resources:
try
{
InetAddress serverAddress = InetAddress.getByName("servername");
try (
Socket socket = new Socket(serverAddress, 9999);
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
) {
while ((userInput = input.readLine()) != null) {
System.out.println(input.readLine());
}
}
}
catch (...)
First, each call readLine() tries to read line from input stream.
In userInput = input.readLine() you read header, but println(input.readLine()) read body and print in console.
while ((userInput = input.readLine()) != null) {
System.out.println(userInput); //instead input.readLine()
}
Second, I didn't use nc, but I think problem will solve if you will close socket (and reader) in finally statement.
I hope it would be helpful.
For the first question: you were trying to print userInput string. But it's printing the result of another readline() call.
For the second: after the file has been transferred, you have to stop and restart nc; no matter what you do from your side. It's from nc side.
See the nc documentation.
I'm learning distributed systems basics and currently I'm trying to do a simple yet realistic messenger between one server and one client. What I do intend is that on each endpoint socket side (Server and Client) text automatically updates (like a real "messaging app"). In other words, I want that the moment I write and "send" the message, it automatically appears on recipient side. What I have now follows this schema:
I send a message (let's assume from client)
To see that message on Server's side I need to reply first (because Server's BufferedReader / Client's PrintWriter is only read after asking for the answer)
My code:
public class ClientSide {
public static void main(String [] args){
String host_name = args[0];
int port_number = Integer.parseInt(args[1]);
try {
Socket s = new Socket(host_name, port_number);
PrintWriter out =
new PrintWriter(s.getOutputStream(), true);
BufferedReader in =
new BufferedReader(
new InputStreamReader(s.getInputStream()));
BufferedReader stdIn =
new BufferedReader(
new InputStreamReader(System.in));
String answer;
while ((answer = stdIn.readLine()) != null) {
out.println(answer);
System.out.println("\nlocalhost said\n\t" + in.readLine());
}
} catch (IOException ex) {
Logger.getLogger(ClientSide.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public class ServerSide {
public static void main(String [] args){
int port_number = Integer.parseInt(args[0]);
try {
ServerSocket ss = new ServerSocket(port_number);
Socket tcp = ss.accept();
PrintWriter out =
new PrintWriter(tcp.getOutputStream(), true);
BufferedReader in =
new BufferedReader(
new InputStreamReader(tcp.getInputStream()));
BufferedReader stdIn =
new BufferedReader(
new InputStreamReader(System.in));
String answer;
while ((answer = stdIn.readLine()) != null){
out.println(answer);
System.out.println("\nClient said\n\t" + in.readLine());
}
} catch (IOException ex) {
Logger.getLogger(ServerSide.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
How can I do this? Does it involve advanced knowledge on the matter?
Thanks in advance.
The core problem is that you want to wait for two events concurrently -- either a message from the socket, or input from the user!
You want to wait on both at the same time -- you don't want to be stuck waiting for a message in the socket if the user types a message; nor to be waiting for the user message while you have a new message from the network.
To 'wait' for messages from multiple streams, you have java.nio. I believe it is the most correct way of doing it.
But if you want to keep using the BufferedReader, there is a ready() method that returns true if and only if there is a message waiting to be read.
Your code after the in and stdIn declarations would then look something like (I didn't test it!!):
while(true) {
if(stdIn.ready()) {
System.out.println("I said " + stdIn.readLine());
}
if(in.ready()) (
System.out.println("He said " + in.readLine());
}
}
A few somewhat useful random links:
Java - Reading from a buffered reader (from a socket) is pausing the thread
Is there epoll equivalent in Java?
My program is basically:
Client sends a String to Server,
Based on this String, Server is creating an ArrayList,
ArrayList is sent back to the Client.
What is failing here is:
After Client sends a String, the Server receives it and doesn't do anything else. In this time Client keeps on working and gets a NullPointer.
Client side:
public static ArrayList<String> sendStringToServer(String report) {
Socket socket;
ArrayList<String> fieldsList = new ArrayList<String>();
try {
socket = new Socket("localhost", 2345);
OutputStream os = socket.getOutputStream();
PrintStream ps = new PrintStream(os, true);
ps.println(report);
ps.flush();
//Here the debugger should stop and wait for server to create a List
//at this point there is no answer, code breaks
ObjectInputStream objectInput = new ObjectInputStream(socket.getInputStream());
Object object = objectInput.readObject();
fieldsList = (ArrayList<String>) object;
socket.close();
return fieldsList;
} catch (IOException e1) {
e1.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
Server side:
public class Server {
private ServerSocket serverSocket;
private Socket clientSocket;
private String telegram;
private StringBuilder telegramSB;
public static void main(String[] args) throws IOException, JRException {
new Server();
}
public Server() {
try {
serverSocket = new ServerSocket(2345);
while (true) {
clientSocket = serverSocket.accept();
InputStream is = clientSocket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
try {
//debugger goes to here and then stops
telegram = br.readLine();
int counter = 0;
boolean startSeq = false;
for (char ch : telegram.toCharArray()) {
if (counter == 0 && ch == '/') {
startSeq = true;
}
if (startSeq == true) {
telegramSB = new StringBuilder();
telegramSB.append(ch);
}
if (ch == '\n') {
if (telegram.length() < 255) {
sendListWithFields();
} else {
new Launcher(telegram).run();
}
}
counter++;
}
} catch (JRException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
System.out.println(e);
}
}
My guess here would be that the BufferedReader is waiting to fill its buffer and you haven't sent enough data for it to do that and return so its waiting for more data to come through that never does (because your clients stops writing and starts to read). You could test this theory temporarily by dumping a load more data into the OutputStream on the client and flushing it.
If the above is the case then you probably want to not use BufferedReader but you have other issues here which also mean you probably want to avoid using PrintStream and BufferedReader for communication and serialisation anyway. For example the default character encoding on two different machines and JVMs could be different. When you create your PrintStream and InputStreamReader you don't specify a character encoding so they could end up being mismatched and the string that you write (including the newline character) could end up being understood completely differently by the remote side, this could also be a reason why its blocking (the client side encodes the newline character in one way but the server is expecting it to be encoded a completely different way), though less likely I think .
If you don't have to use PrintStream then I would suggest instead using DataOutputStream / DataInputStream:
//Client
BufferedOutputStream bufout = new BufferedOutputStream(socket.getOutputStream());
DataOutputStream dout = new DataOutputStream(bufout);
dout.writeUTF(report);
dout.flush();
//Server
BufferedInputStream bufin = new BufferedInputStream(socket.getInputStream());
DataInputStream din = new DataInputStream(bufin);
String report = din.readUTF();
You still get buffering from the BufferedIn/OutputStreams so it will be performant but the DataIn/OutputStreams will manage termination of variable length objects for you - they will send a length prefixing the string to tell the other side exactly how many bytes to read, so you don't need to use a special character to terminate the string you wrote, and this also means it doesn't matter what the content of your String is. In your example above even if it was working if your String had a newline character in it the server would read up until that first newline character, not to the end of the string you sent and that would put them out of sync for the next send/receive along that stream.
Using write/readUTF also specifies an encoding (UTF-8) so there is no mismatch there either.
Im trying to make a client/server socket connection via BufferedReader and Buffered Writer, but reader not reading anything it is just hanged, where client send and flush properly.
Server does not throw any exception as if client not sending anything to server.
My head is going go explode...
Im using same for both client and server:
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
Here is the code of server:
//inside of try catch
while(true){
while(!in.ready())// just to debug
System.out.println("READY: " + in.ready()); //just to debug
System.out.println("READY: OK"); //just to debug
msg = receive().toString(); //hangs here...
System.out.println("KEYIS: " + msg);
///some stuff to do ....
public StringBuilder receive() throws IOException {
StringBuilder str = new StringBuilder();
int tmp;
while(true){
tmp = in.read();
if(tmp == 0)
break;
else if(tmp == -1)
throw new IOException();
str.append((char)tmp);
}
return str;
}
Client code: not hanging here
//inside of try catch
send(KEY); //sended properly, no exception
while(true){
send(KEY); // sended properly, no exception
System.out.println("sent");
//System.out.println(receive().toString());
}
public void send(String str) throws IOException{
out.write(str + "\n"); //
//out.newLine(); //tried too, not helped
out.flush(); //push message to server
}
Well server waits for if(tmp == 0) which is 0 is a nil, and the client never sends it.
I think You are waiting about \n which it's not 0, it's 10(line feed).
Just wondered why don't you use DataOutputStream#writeUTF() and DataInputStream#readUTF()?
You're writing lines but you have a pretty pointless and elaborate and very buggy input method which doesn't actually read lines, and which throws the wrong exception at end of stream.
Try BufferedReader.readLine(), not forgetting to test for null.
StringBuffer sb = new StringBuffer();
int i;
while ((i = bi.read()) != -1) {
char c = (char) i;
sb.append(c);
}
return sb.toString();
Solved the problem... So stupid mistake... I just forgot to add a \0 to determine the end of message, so recieve method was waiting as if more data coming...