try (
InputStream reader = socket.getInputStream();
OutputStream writer = socket.getOutputStream()
) {
byte[] bytes = new byte[4096];
int byteLength = reader.read(bytes);
String message = new String(bytes, 0, byteLength, StandardCharsets.UTF_8);
writer.write("response message".getBytes());
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
try (
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
OutputStream writer = socket.getOutputStream()
) {
String message = reader.readLine();
writer.write("response message".getBytes());
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
I made server socket. It returns response message when it receives message from client socket.
When I use only InputStream (first code), the client socket gets response message.
However when I use BufferedReader (second code), the client socket cannot get response message.
The way I send response message is same.
How I receive message is the only different.
What's wrong with the second code?
What's the difference between them?
Related
I have to connect with a server (I donĀ“t have access to the server code) but the transmission protocol (Socket) is:
(client) --> data
ack <-- (server)
data response <-- (server)
(client) --> ack
It's assumed that the server should always respond quickly. I connect to the server, I send the data but the response is NULL and if I debug my code, an exception occurs when I catch the response:
"java.net.SocketException: Software caused connection abort: recv failed"
My code:
public static void main(String[] args){
try{
String order = "datahere";
String responseServer;
BufferedReader inFromUser = new BufferedReader( new InputStreamReader(System.in));
Socket clientSocket = new Socket();
InetSocketAddress sa = new InetSocketAddress("XXX.XX.XX.XX", 9300);
clientSocket.connect(sa,500);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
outToServer.writeBytes(order);
responseServer = inFromServer.readLine();//exception if I try to debug my code
System.out.println("From server: " + responseServer); //responseServer is NULL
clientSocket.close();
} catch (IOException ex) {
System.out.println("Error: "+ex);
}
}
That's wrong? Any idea?
I tried to disable the firewall and also add a rule for the port 9300 but the result is the same.
The client gave me an example code in Vb.Net that it's supposed to work and I try to replicate it in Java.
Code in Vb.Net:
Dim message As String = "datahere";
Try
Dim data As [Byte]() = System.Text.Encoding.ASCII.GetBytes(message)
Dim client As New TcpClient(ip, port)
Dim stream As NetworkStream = client.GetStream()
stream.Write(data, 0, data.Length)
data = New [Byte](2048) {}
Dim responseData As [String] = [String].Empty
Dim bytes As Integer = stream.Read(data, 0, data.Length)
responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes)
stream.Close()
client.Close()
Catch ex As Exception
End Try
SOLUTION:
Socket clientSocket = new Socket();
InetSocketAddress sa = new InetSocketAddress("XXX.XX.XX.XX", 9300);
clientSocket.connect(sa,500);
clientSocket.getOutputStream().write(order.getBytes("ASCII"));
byte[] data = new byte[2048];
int bytes = clientSocket.getInputStream().read(data, 0, data.length);
String responseData = new String(data, 0, bytes, "ASCII");
System.out.println("From server: " + responseData);
//Another way to catch the response:
//InputStreamReader in = new InputStreamReader(clientSocket.getInputStream());
//int data1 = in.read();
//while(data1 != -1) {
// System.out.print((char) data1);
// data1 = in.read();
//}
clientSocket.close();
Here is a translation of your VB code in java
public static void main(String[] args) throws IOException {
String order = "datahere";
// Try-with-resource statement will close your socket automatically
try (Socket clientSocket = new Socket("XXX.XX.XX.XX", 9300)) {
// Send to the sever the order encoded in ASCII
clientSocket.getOutputStream().write(order.getBytes("ASCII"));
// Sleep until we have bytes to read available
while (clientSocket.getInputStream().available() == 0) {
Thread.sleep(100L);
}
// Create the buffer of exactly the amount of bytes available without blocking
byte[] data = new byte[clientSocket.getInputStream().available()];
// Read the bytes from the server and put it into the buffer
int bytes = clientSocket.getInputStream().read(data, 0, data.length);
// Decode what has been read from the server that was encoded in ASCII
String responseData = new String(data, 0, bytes, "ASCII");
System.out.println("From server: " + responseData);
}
}
DataInputStream dis = new DataInputStream( new InputStreamReader(clientSocket.getInputStream()));
while(dis.available()>0){
//reads characters encoded with modified UTF-8
String temp = dis.readUTF();
System.out.print(temp+" ");
}
try to use a dataInputStream instead of bufferedReader and use readUTF() method in dataInputStream to read UTF characters.
My application communicates between a server and a client using DataInputStream and DataOutputStream. The client will be requests from a website to my application, so I created a test client to test input that could come from the website.
The method I decided to use would be that the client would send an integer first deciding the size of the data to be sent and then it would send the data. So, I was testing this method and it worked for the first string of data, but not the second and gave me an EOF error on the second try. I understand why it gave me an EOF because the client closed the connection, but I still have not read the incoming bytes, so the stream should still have more to read from.
Client Code:
Socket socket = new Socket("127.0.0.1", 9000);
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
os.writeInt("Test String".length());
os.write("Test String".getBytes());
os.flush();
os.writeInt("String".length());
os.write("String".getBytes());
os.flush();
os.close();
socket.close();
Server Code:
byte[] data;
try{
DataInputStream input = new DataInputStream(client.getInputStream());
DataOutputStream output = new DataOutputStream(client.getOutputStream());
client.setSoTimeout(SOCKET_TIMEOUT);
logger.log(Level.INFO, "Client connected with IP: " + client.getInetAddress());
data = readNextPacket(input);
if(!(new String(data).contains(PROTOCOL_HEADER)))
throw new IOException("Invalid request from client.");
else
logger.log(Level.INFO, "Valid header: " + new String(data));
data = readNextPacket(input);
logger.log(Level.INFO, new String(data));
}catch(IOException e){
logger.log(Level.SEVERE, e.getMessage(), e);
}finally{
try {
client.close();
} catch (IOException e) {
logger.log(Level.SEVERE, e.getMessage(), e);
}
logger.log(Level.INFO, "FINISHED");
}
readNextPacket Method:
private byte[] readNextPacket(DataInputStream stream) throws IOException{
int bytesToRead = stream.readInt();
ByteArrayOutputStream os = new ByteArrayOutputStream();
if(bytesToRead <= MAX_BYTES){
byte[] data = new byte[bytesToRead];
while(stream.read(data) != -1 && os.size() < bytesToRead){
os.write(data);
}
}
return os.toByteArray();
}
Stack Trace:
java.io.EOFException
at java.io.DataInputStream.readInt(DataInputStream.java:392)
at com.schmidt73.bidwriter.handlers.SocketHandler.readNextPacket(SocketHandler.java:1)
at com.schmidt73.bidwriter.handlers.SocketHandler.parse(SocketHandler.java:16)
at com.schmidt73.bidwriter.handlers.SocketHandler.start(SocketHandler.java:43)
at com.schmidt73.bidwriter.BidWriter.main(BidWriter.java:21)
Okay, so basically my readNextPacket() method would read more data than specified if the entire buffer wasn't read the first time. So, I changed some of the code to fix it by adding an offset and subtracting the amount I've already read to the read() method. However, I realized that would be basically copying the readFully() method and there is no reason to do that, so I just implemented that into the readNextPacket() method.
Here is the new working code:
private byte[] readNextPacket(DataInputStream stream) throws IOException{
int bytesToRead = stream.readInt();
byte[] data = new byte[bytesToRead];
stream.readFully(data);
return data;
}
I'm writing a simple server in Java, and I'm able to retrieve incoming data from the client on the server side, but not on the client side due to a 2000ms timeout. Anyone know why this times out?
This is the server's code:
private static void listen() throws IOException {
while(true) {
Socket clientSocket = serverSocket.accept();
StringBuilder bufferedStringInput = new StringBuilder();
CharBuffer cbuf = CharBuffer.allocate(4096);
try {
InputStream is = clientSocket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF8"));
int noCharsLeft = 0;
while ((noCharsLeft = br.read(cbuf)) != -1) {
char[] arr = new char[noCharsLeft];
cbuf.rewind();
cbuf.get(arr);
bufferedStringInput.append(arr);
cbuf.clear();
}
System.out.println(bufferedStringInput.toString());
} catch (IOException e) {
System.out.println("Error received client data: " + e.getMessage());
}
String message = "Hello client";
try {
PrintWriter out = new PrintWriter(clientSocket.getOutputStream());
out.print(message);
} catch (IOException e) {
System.out.println("Error getting output stream from client: " + e.getMessage());
}
clientSocket.close();
}
}
You're reading the input until end of stream, which only happens when the peer closes the connection, then you're trying to write to it, so of course you get a broken pipe. Doesn't make sense. You should just read the input until you have one entire request, whatever that means in your protocol.
There are other problems lurking here:
If the client code uses readLine(), you're not sending a line terminator: use println(), not print(), and close the PrintWriter, not just the client socket.
cbuf.rewind()/get()/clear() should be cbuf.flip()/get()/compact().
But it would make more sense to read directly into a char[] cbuf = new char[8192]; array, then bufferedStringInput.append(cbuf, 0, noCharsLeft), and forget about the CharBuffer altogether. Too much data copying at present.
noCharsLeft is a poor name for that variable. It is a read count.
Client code:
try {
Socket socket = new Socket(ip, port);
OutputStream output = socket.getOutputStream();
ObjectOutputStream out = new ObjectOutputStream(output);
InputStream input = socket.getInputStream();
ObjectInputStream in = new ObjectInputStream(input);
out.writeByte(1);
FileHandler fh = (FileHandler) in.readObject();
//processing stuff
out.flush();
out.close();
output.flush();
output.close();
input.close();
in.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
Server code:
try {
ServerSocket server = new ServerSocket(port);
Socket socket = server.accept();
InputStream input = socket.getInputStream();
ObjectInputStream in = new ObjectInputStream(input);
int type = in.readByte();
//processing stuff (which includes closing the streams and sending FileHandler object)
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
The server never receives the byte. It just waits for the byte from the client, and it never comes. I'm not sure why it isn't sending, or getting received. Any help is much appreciated.
If I had to make a guess it's because in your client you block on in.readObject(); waiting for the server to send you something thus never flush the output stream thus ... nothing ever gets sent.
Move your read to after you flush your output stream.
Try to use the writeObject and readObject methods. Also write an Integer not an int to the stream. Read this really good lecture before proceeding any further.
This is also a good lecture for your problem.
Regards!
yes i did look at the tutorials on sun and they didn`t help in my case, only transferred the first command.
I`ve got a method
public void openConnection() throws IOException{
serverSocket = new ServerSocket(5346);
Socket simSocket = serverSocket.accept();
is = simSocket.getInputStream();
os = simSocket.getOutputStream();
writer = new PrintWriter(os);
isReader = new InputStreamReader(is);
reader = new BufferedReader(isReader);
System.out.println("Connection succesfull.");
}
and
public void sendTo(int command) {
try {
writer.println(command);
writer.flush();
} catch(Exception e) {
System.out.println("Error sending command to the robot");
System.out.println(e.toString());
}
}
in the sending side, and
public static void setUpConnection() {
try {
socket = new Socket(InetAddress.getLocalHost(), 5346);
is = new InputStreamReader(
socket.getInputStream());
reader = new BufferedReader(is);
writer = new PrintWriter(socket.getOutputStream());
System.out.println("Simulator: connection succesful");
} catch (IOException e) {
e.printStackTrace();
}
}
and
while (true) {
intCommand = reader.read();
ett = reader.readLine(); // does nothing, but without this line it doesn't work
command = (char) intCommand;
in the receiving side. It works perfectly sending a char or an ascii number of a char. What i need is to change this code to send integers or simply array of bytes instead of a char. if i simply leave just InputStream and OutputStream it does receive the first command and thats it, while these methods continuously receives what is sent through sendTo. Even in sockets documentation they only have exmample with sending chars only.
Just code your server to store the received value as an int instead of a char.