So I have set up a basic client/server connection and I am trying to send a message to one another on connection, I got the client to receive the message from the server, but the server doesn't recieve the clients message. Here is my current code for reading the sent data from the client:
ServerThread.socket = new ServerSocket(5556);
Socket client = ServerThread.socket.accept();
DataInputStream in = new DataInputStream
(
new BufferedInputStream(client.getInputStream())
);
String s = in.readUTF();
System.out.println("Client: " + s);
Using that it doesn't print out anything, Not even just 'Client: '
Here is my code for my client connection, and sending the message. Note: I wrote this part in VB:
client = New TcpClient()
client.Connect("myiphere", 5556)
Dim stream As NetworkStream = client.GetStream()
Dim sendBytes As [Byte]() = Encoding.ASCII.GetBytes("Hello server")
stream.Write(sendBytes, 0, sendBytes.Length)
Is there any reason why the data isn't being recieved? Or why it is being delayed? I have tried surronding the Java portion of the code with a try catch block but no error is emitted.
Any help will be appreciated.
UTFs in a DataInputStream are prepended with 0 and the length.
I haven't done much with VB, so I don't know if there are other errors, but try:
stream.Write(0, sendBytes.Length, sendBytes)
I shouldn't suggest code in a language I don't know. If you want to read it with readUTF, you'll have to send a 0 byte and a byte equal to the length of the string before you send your text bytes.
Edit:
You really might not want to use DataInputStream at all, though. It's intended for storing binary streams. If you're receiving text, try this on the Java side:
BufferedReader in = new BufferedReader(
new InputStreamReader(
client.getInputStream()
)
);
String s = in.readLine();
If you're not sending text, just create a BufferedInputStream as you did and read the bytes off of it.
As maybeWeCouldStealAVan pointed out, readUTF expects two bytes indicating how many more bytes of content there are. See http://docs.oracle.com/javase/6/docs/api/java/io/DataInput.html#readUTF() for details.
However, his/her solution using InputStreamReader doesn't work because InputStreamReader is expecting UTF-16 input (two bytes per character), but your VB client is sending ascii. I would suggest making your VB client send UTF-16 if you can (then using maybeWeCouldStealAVan's java code). If you can't do that (sorry, I don't know what encodings VB allows), then just write the extra two bytes needed to make readUTF work.
Related
I have been trying to send a byte[] array across my client / server application using Sockets, DataInputStream and DataOutputStream, but on the server side, the program just gets stuck when I try to initialise the DataInputStream.
Here is the code on the client side (it works fine):
DataOutputStream datas = new DataOutputStream(connection.getOutputStream());
datas.flush();
byte[] send = identityKeyPair.serialize();
datas.write(send);
datas.flush();
Here is the code on the server side:
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()) );
sender = new PrintWriter(connection.getOutputStream());
newUser = new BasicUserData();
System.out.println("New registration from: " + connection.getInetAddress());
System.out.println("Data:");
String un = reader.readLine();
newUser.USERNAME = un;
System.out.println(newUser.USERNAME);
String pw = reader.readLine();
newUser.PASSWORD = pw;
System.out.println(newUser.PASSWORD);
DataOutputStream dataout = new DataOutputStream(connection.getOutputStream());
System.out.println("Opened data output stream");
DataInputStream receiver = new DataInputStream(connection.getInputStream());
//It gets stuck here, and the program doesn't read anything further
receiver.read();
byte[] id = receiver.readAllBytes();
System.out.println("Opened data input stream");
You are using both connection.getInputStream() and connection.getOutputStream() in two different ways. You should use one and only one way of reading from and writing to streams, don't mix multiple ways.
When you execute reader.readLine(), the BufferedReader called reader will read up-to 8192 characters from the input stream into its buffer, likely consuming all bytes your client has written. This means that when you construct your DataInputStream around that same input stream and try to read it, there is no data available to read, causing the receiver.read() to block waiting for data. That data is never received as your client has sent all its data, which is now buffered in reader.
In addition, unless your client has closed its output stream, InputStream.readAllBytes() will block indefinitely anyway, because it is only finished when the end-of-stream has been reached. And for socket communication, that only happens when the other side closed its output stream.
Change your code so there is only one way of writing data (though not relevant here), and one way of reading data. In addition, you should establish clearly how you need to read and write data in a protocol, so to avoid consuming too much data at the wrong point, and to know how much data you need to read when.
Of course it does nothing but wait as specified in the javadoc a call to DataInputStream#read() blocks the current thread until data can be read from the input stream.
Your reader = BufferedReader(...) uses the same underlying InputStream which means the all the data the client sent is most likely already consumed by the 'login' logic.
Since neither the client nor the server close their respective streams no EOF is emitted either which leads to the stream 'just dangling' around waiting for more data.
Unless your client sends more data the server will wait eternally.
There are two solutions for your issue.
Either thread you application so that the 'await input' logic is in it's own thread or take a look at javas NIO package (more precisely Channels and Selectors)
I am trying to let Flink read some streaming text input from a socket connection.
In my input socket's code, I used the following to publish the text for Flink to receive:
outputStream.writeUTF(new String(message.getPayload()));
However, in Flink, I couldn't read the incoming text even though the connections are working. I Google-d and found that I might need to read the text using readUTF(). In other word it's mainly due to encoding. However, these are done on InputStream; Flink doesn't have that as my inputs are in the form of DataStream<String>:
DataStream<String> text = env.socketTextStream("localhost", port, "\n");
Can anyone advise me on this? Thank you!
writeUTF() does not produce 'words encoded in UTF'. It produces a specific format with a 16-bit length-word prefix that only readUTF() can understand. If you don't want to use readUTF() you can't use writeUTF() either. Use writeBytes() or whatever else suits your reading code.
What is your program trying to accomplish?
These are the use cases for Flink, and if you are not trying to achieve one of these, I would recommend using Java sockets if you are just doing low-level network communication
If using Java, it is quite simple. You need to get the data input stream from the socket, then convert the incoming bytes back into a string. For example, here is what has worked for me
Socket socket = new Socket(HOST_IP, PORT);
DataInputStream in = new DataInputStream(socket.getInputStream());
byte[] buffer = new byte[256];
while ((i = in.read(buffer, 0, buffer.length)) != -1)
{
String input = new String(buffer, "UTF-8");
}
I'm trying to implement a server and it does something like this when it receives a message:
try{
ObjectInputStream is = new ObjectInputStream(clientSocket.getInputStream());
String message = (String)is.readObject();
ActivateCommand(message,clientSocket);
is.close();
}
and the ActivateCommand:
private void ActivateEwolfCommand(String msg, Socket clientSocket) throws IOException
{
ObjectOutputStream os = new ObjectOutputStream(clientSocket.getOutputStream());
Gson gsonObject = new Gson();
.
//code which makes a Json string
.
os.writeObject(json);
os.close();
}
now, when i tested it with sending a message to the local host with a junit test it worked. But when tried connecting to the server from a C# client, the client connected but the server throw an EOF exception when getting to the point of clientSocket.getInputStream().
I'm guessing it happens because the server did not know when the message is suppose to end but i don't know if thats really the case and if it is, then how can i fix it?
When there is no more data available on the InputStream to read() - that basically is what causes an EOF. How much data is available is determined by the client - the data that it writes to the Socket's OutputStream on its side appears as such on the InputStream of Socket of the server side. You can call InputStream.available() to get an estimate of number of bytes that can be still read().
However your code is trying to read an Object using an ObjectInputStream - this class has its own protocol to read a serialized byte stream and convert that to an object - if it does not find the bytes to complete the task this can throw the EOF exception. If your client is in C# - the format of bytes this writes for a serialized object will definitely not be the same as expected by the ObjectInputStream on the server side.
This is why it's a bad idea to create your own client-server protocol with a socket and object streams. Many people have spent many years bringing you, oh, well:
SOAP
REST
RMI
Hessian
CORBA
Thrift
and the multitude of other protocols out there. Surely one of them, if not 5 or 6, is good enough to solve your problem, including all issues of framing.
If you want to send strings over a socket, then an ObjectInputStream or ObjectOutputStream isn't the right stream implementation. These stream implementations use Java object serialization. Even if you serialize String instances, the resulting bytes are not the same as plain string to byte conversion with the appropriate character encoding.
And a C# application doesn't understand Java serialization at all.
Consider using a PrintWriter to write strings to your stream and a BufferedReader for reading.
PrintWriter writer = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream(), "UTF-8"));
writer.println(...);
BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), "UTF-8"));
String line = reader.readLine();
Then you can read and write strings line by line.
This is only a starting point. If you want to implement your own protocol you have to pay attention to some more points. As an example you can read the specifications for some TCP protocols like POP3, FTP or HTTP 1.0.
I've written a socket listener in Java that just sends some data to the client.
If I connect to the server using telnet, I want the server to send some telnet option codes. Do I just send these like normal messages?
Like, if I wanted the client to print "hello", I would do this:
PrintWriter out = new PrintWriter(clientSocket.getOutputStream());
out.print("hello");
out.flush();
But when I try to send option codes, the client just prints them. Eg, the IAC char (0xff) just gets printed as a strange y character when I do this:
PrintWriter out = new PrintWriter(clientSocket.getOutputStream());
out.print((char)0xff);
out.flush();
If you use the default character encoding I would expect 0xff to be turned into two characters.
I suggest you use the plain OutputStream without a PrintWriter. That way the bytes will be sent without translation.
I just answered that here
I have the following Java socket client app, that sends same string to socket server:
import java.net.*;
import java.io.*;
public class ServerClient {
public static void main(String[] args) throws IOException {
System.out.println("Starting a socket server client...");
Socket client = new Socket("XXX.X.XXX.XX", 12001);
BufferedOutputStream stream = new BufferedOutputStream(client.getOutputStream());
String message = "ABC";
BufferedReader inputReader = new BufferedReader(new InputStreamReader(System.in));
String input = null;
while ( true ) {
System.out.print("Would you like to send a message to Server? ");
input = inputReader.readLine();
if ( !input.equals("Y") ) break;
System.out.println("Message to send: " + message);
System.out.println("Message length is: " + message.length());
byte[] messageBytes = message.getBytes("US-ASCII");
stream.write(messageBytes, 0, messageBytes.length);
stream.flush();
}
System.out.println("Shutting down socket server client...");
stream.close();
client.close();
inputReader.close();
}
}
The first time message is sent, server receives the message; however, every subsequent time I'm trying to send this message, server is not receiving anything. Message simply disappears. I am writing to the socket successfully (no exceptions) but nothing is coming on the other side of the pipe (or so I'm told).
I do not have access to the server app, logs or code, so I'm wondering if there is any approach you can recommend to figure out why server is not receiving subsequent messages. Any ideas would be greatly appreciated!
Clarification:
New lines are not expected by the server; otherwise, how would it even receive message the first time? As a trial and error, I did try sending '\n' and "\r\n" and 0x00 characters at the end of the string - all without any luck.
I thought flushing was an issue, so I tried various outputstream classes (PrintStream, PrintWriter, FilterOutputStream), but was still running into same exact issues. Then, if "flushing" is an issue, how is it working the first time?
Other tests:
1 - use a network sniffer to see what is realy hapening on the network
2 - use some program like TCP Test Tool to send data to the server and simulate your program. (netcat can also be used, but it sends a newline after each line)
Remember:
TCP is stream oriented. not message oriented.
One write on the client could take several reads on the server to .. read
Multiple writes on the client could get read by the server in one read
You'll hardly see the above scenarios in a test application on a local network, you will see them very quick in a production environemnt, or when you start to really speed up the sending/receiving.
Following this, if you are sending messages you need a delimiter, or some other way of indicating 'here's one message', e.g. defining the protocol to be 'the first byte is the length of the following message'.
And you'd need to check the receiving end wether it read a partial message, a whole message, and any combination thereof (e.e.g one read might have read 3 and a half message..).
A quick solution for your test app, write lines. That is, a string followed by a newline character. A bufferedreader's ReadLine() could then take care of the reassembly for you on the receiving end.
It works correctly here... but I am missing a carriage return or some other end of message after sending the message.
Hard to write more without knowing what the server expects (protocol)...
Maybe you should try something like
String message = "ABC\n";