I am a total noob at Java, so apologies if this is a rookie mistake. I was trying out Java NIO, I still haven't gotten to a stage where I am using the non-blocking feature. I just am not able to get the server to read a string, I understand its not easy to send a Bytebuffer from one side and trying to interpret it as String on the other side, but i still can't figure out where I am going wrong. Here is the code
*****************************SERVER SIDE**************************************
class MyBlockingServer extends Thread
{
private int M_PortNumber;
private ServerSocket M_ServerSocket;
MyBlockingServer(int PortNumber)
{
M_PortNumber = PortNumber;
try {
M_ServerSocket = new ServerSocket(M_PortNumber);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run()
{
int my_number = 0;
while(true)
{
try {
Socket Server = M_ServerSocket.accept();
DataInputStream inputStream = new DataInputStream(Server.getInputStream());
System.out.println("[SERVER]" +inputStream.readUTF());
DataOutputStream outputStream = new DataOutputStream(Server.getOutputStream());
outputStream.writeUTF("Thanks for connection, you suck tata" + " "+ my_number);
my_number++;
Server.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
void socket_close()
{
try {
M_ServerSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class JavaBlocking
{
public static void main(String []args)
{
MyBlockingServer Server = new MyBlockingServer(8000);
try {
Server.start();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
*******************************CLIENT SIDE*********************************
public class JavaChannels
{
public static void main(String []args)
{
SocketChannel client_channel = null;
try {
client_channel = SocketChannel.open();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("[Client] Socket channel open");
try {
client_channel.connect(new InetSocketAddress("127.0.0.1",8000));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("[Client] Socket channel connected");
ByteBuffer my_buffer = ByteBuffer.allocate(48);
my_buffer.clear();
try {
my_buffer.put("WHY_YOU_NO_WORK".getBytes("UTF-8"));
} catch (UnsupportedEncodingException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
my_buffer.flip();
try {
int bytes_written = client_channel.write(my_buffer);
while(my_buffer.hasRemaining())
{
bytes_written = client_channel.write(my_buffer);
}
System.out.println("[Client] Wrote "+ bytes_written +" bytes");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("[Client] Socket channel write finished");
my_buffer.clear();
my_buffer.flip();
try {
client_channel.read(my_buffer);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println("[Client] server says" + new String(my_buffer.array()));
try {
client_channel.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The error i keep getting is
java.io.EOFException at java.io.DataInputStream.readFully(DataInputStream.java:197) at java.io.DataInputStream.readUTF(DataInputStream.java:609) at java.io.DataInputStream.readUTF(DataInputStream.java:564) at netty_tutorial.blocking.MyBlockingServer.run(JavaBlocking.java:39)
This somehow indicates to me that readUTF is not reading UTF format but something else.
In summary what i am doing is
Server --> ReadUTF
Client --> String -->Byte Array in UTF-8 --> ByteBuffer -->Write
As I am explicitly encoding the byte array into UTF-8. why can't readUTF read it?
The DataInput.readUTF
method doesn't read a UTF-8 encoded string, it reads data in the specific format that DataOutput.writeUTF
creates, which is similar to but not the same as true UTF-8:
If you are writing true UTF-8 then you need to read true UTF-8, if you want to readUTF
then you must writeUTF
.
If you want to writeUTF
to a ByteBuffer
it's pretty straightforward to implement an OutputStream
wrapper around the buffer, which you can in turn wrap in a DataOutputStream
:
class ByteBufferBackedOutputStream extends OutputStream{
ByteBuffer buf;
ByteBufferBackedOutputStream( ByteBuffer buf){
this.buf = buf;
}
public synchronized void write(int b) throws IOException {
buf.put((byte) b);
}
public synchronized void write(byte[] bytes, int off, int len) throws IOException {
buf.put(bytes, off, len);
}
}
(source)