I'm beginning client-server programming. what I'm trying to do is basically a Echo server but instead of return the same thing as the client inserted, I want the server to return 2*(The number I insert).
I have the following server:
public class Server {
public static void main(String args[]) throws Exception {
ServerSocket server = new ServerSocket(6789);
while(true) {
try {
Socket aux = server.accept();
DataInputStream dis = new DataInputStream(aux.getInputStream());
DataOutputStream dos = new DataOutputStream(aux.getOutputStream());
int total = 0;
while(dis != null) {
int res = dis.read();
total = 2*(res);
dos.writeInt(total);
}
}
catch (EOFException e) {
out.println("The client exit!");
continue;
}
}
}
}
And the following client:
public class Client {
public static void main(String args[]) throws Exception {
Socket client = new Socket("localhost", 6789);
DataInputStream dis = new DataInputStream(client.getInputStream());
DataOutputStream dos = new DataOutputStream(client.getOutputStream());
BufferedReader input = new BufferedReader(new InputStreamReader(in));
while(true) {
int fromClient = input.read();
dos.writeInt(fromClient);
client.shutdownOutput(); //to show to the server the end of file
int fromServer = dis.readInt();
out.println(fromServer);
}
}
}
Can somebody help please?
I got the following error on the server side:
Exception in thread "main" java.net.SocketException: Broken pipe
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:109)
at java.net.SocketOutputStream.write(SocketOutputStream.java:132)
at java.io.DataOutputStream.writeInt(DataOutputStream.java:197)
at Server.main(Exercicio3.java:21)
And on the client side when I insert a value (in this case '1'):
1
0
Exception in thread "main" java.net.SocketException: Broken pipe
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:109)
at java.net.SocketOutputStream.write(SocketOutputStream.java:132)
at java.io.DataOutputStream.writeInt(DataOutputStream.java:197)
at Client.main(Exercicio4.java:25)
Thanks
Without knowing what your problem is, one issue I can see is:
int res = dis.read();
res is the next byte in the input (see the doc) and is not an integer as entered by your user. It will be the first byte of the character code of whatever your user has entered.
There is an infinite loop before you send the result back to the
client.
while(dis != null) {
int res = dis.read();
total = 2*(res);
}
dos.writeInt(total);
Move that last line inside the brackets and it should work.
while(dis != null) {
int res = dis.read();
total = 2*(res);
dos.writeInt(total);
}
Additionally, calling client.shutdownOutput() is not necessary. You
will just get exceptions when you try to write to it the next time:
Disables the output stream for this socket. For a TCP socket, any previously written data will be sent followed by TCP's normal
connection termination sequence. If you write to a socket output
stream after invoking shutdownOutput() on the socket, the stream will
throw an IOException. `
And then there is also the issue mentioned previously:
int res = dis.read();
should be
int res = dis.readInt();
You have a similar issue reading the user's input in the client.
Use this instead:
int fromClient = Integer.parseInt(input.readLine());
Related
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);
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?
I want to send some data using TCP Socket;
keyboard input is ok.
redirecting binary files fine too.
but
when I redirect /dev/urandom to stdin (java prog < /dev/urandom) nothing happens, no errors, no data send.
public class P1{
static DataInputStream dis = new DataInputStream(System.in);
int port = 12345;
String host = "127.0.0.1";
Socket p1Socket;
DataOutputStream out;
byte data;
void run() {
try{
p1Socket = new Socket( host, port );
out = new DataOutputStream(p1Socket.getOutputStream());
while (dis.available() >0){
data = dis.readByte();
out.write ( data );
}
out.flush();
out.close();
p1Socket.close();
}catch(Exception e){
e.printStackTrace();
}
}
public static void main(String args[]) throws IOException {
P1 p1 = new P1();
while (dis.available() <=0);
p1.run();
}
}
Don't use the available method, it only tells you if something can be read without blocking, which is pretty useless. Use an infinite loop instead.
while (true) {
data = dis.readByte();
out.write(data);
}
End-of-file is signaled with EOFException. Make sure that you close the file when exceptions are thrown.
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...