I was thinking about how you would read how much data you send over a Socket. For example if I made a Chat Application and then wanted to find out how much a message would take (in kilobytes or bytes), how would I measure this?
I send a message like "Hello, world!". How do I measure the amount of bandwidth that would take to send?
I know there are programs to monitor how much data is sent and received over the wire and all that, but I wanted to try and do this myself to learn some.
Wrap the socket's output stream in a CountingOutputStream:
CountingOutputStream cos = new CountingOutputStream(socket.getOutputStream());
cos.write(...);
System.out.println("wrote " + cos.getByteCount() + " bytes");
If you send raw string with no header (protocol)
For the strings you have
String hello = "Hello World";
hello.getBytes().length //size of the message
For showing progress to user when sending files you can do this
Socket s = new Socket();
//connect to the client, etc...
//supose you have 5 MB File
FileInputStream f = new FileInputStream( myLocalFile );
//declare a variable
int bytesSent = 0;
int c;
while( (c = f.read()) != -1) {
s.getOutputStream().write(c);
bytesSent++; //One more byte sent!
notifyGuiTotalBytesSent(bytesSent);
}
well, thats just a very simple implementation not using a buffer to read and send the data just for you get the idea.
the method nitify.... would show in the GUI thread (not this one) the bytesSent value
Related
I have a small J2ME app that should send some bytes to a socket and read response. However, when I close OutputStrean, the socket closes too, and I can't read response. I thought I could try OutputStream.flush();, but it does nothing.
Here is my readAll() method that should read data from OutputStream:
public final static String readAll(InputStream d) throws IOException {
ByteArrayOutputStream res = new ByteArrayOutputStream();
byte[] bytes = new byte[1024];
int length;
while ((length = d.read(bytes)) != -1){
res.write(bytes, 0, length);
}
return new String(res.toByteArray(), "UTF-8");
}
You'll typically want to have a thread running in the background that handles actually sending and receiving data.
The data that is received should provide some way of determining when that particular chunk of data terminates. For example, the server might send back:
(long)length+(byte[])data
So from the stream you would read in take 8 bytes + whatever the length is, then you would use that data to construct an object that represents that message and your other thread would read in that data to decide what data it wants to send out.
In order to send data out you would effectively do the reverse, with a separate thread consuming objects that represent messages to be sent.
These are called message queues and you can read more about them here: https://en.wikipedia.org/wiki/Message_queue
I am trying to send two byte arrays over a Java socket. I have captured the data via wireshark and it shows that the first byte array sends; the second, however, doesn't send at all.
I am using Linux Mint and Oracle's JRE (not OpenJDK).
byte[] packet_one = new byte[] {(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x50};
byte[] packet_two = new byte[] {(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x78};
Socket sck;
DataInputStream dis;
DataOutputStream dos;
try {
sck = new Socket(IP_ADDRESS,PORT);
dis = new DataInputStream(sck.getInputStream());
dos = new DataOutputStream(sck.getOutputStream());
int recv_header = dis.ReadInt(); // This receives the correct response.
dos.write(packet_one); // Sends fine.
dos.write(packet_two); //Does not send.
int data_length = dis.readInt(); // No more data received.
}catch(Exception e) {
System.out.println("Error: " + e.getMessage());
}
So, dos.write(packet_one) works (confirmed by wireshark). Writing packet_two doesn't work. The data_length returns 0 since I don't receive anymore data either. No errors or exceptions get caught.
I have also tried using dos.flush(), but it doesn't make a difference.
Any ideas on why this may be the case?
Maybe you're exiting the program before there's time to send the buffered bytes?
Perhaps if you add something like:
for (;;) {
final byte x = dis.readByte();
System.out.println("got byte: " + (x & 0xFF));
}
the program won't exit, and you'll also see if there are more bytes that the server sent back. Might offer clues.
And, in case you don't know, readInt() reads for bytes and returns an int made from those bytes, which is 0 if all the for bytes read are zero. So your comment 'No more data received.' feels a bit ambiguous.
You could also try inserting a
sck.setTcpNoDelay(true);
after creating the socket. Writes should then go on the network immediately. I think.
Hope this helps.
I've been playing around with transferring data between a test client (written in Java) and a server (written in C#/.NET).
I tried TCP clients and servers, but there has been and current is a problem flushing the stream. I realize flush doesn't always flush the stream, so I'm wondering if there is any way to flush/send a stream without .flush() or in a more reliable way?
Currently, the important part of the client looks like this (message is a string, serverSocket is a Socket object):
OutputStream output = serverSocket.getOutputStream();
byte[] buffer = message.getBytes();
int length = buffer.length;
output.write(ByteBuffer.allocate(4).putInt(length).array());
output.write(buffer);
output.flush();
and the server looks like this:
NetworkStream stream = client.GetStream ();
byte[] sizeBuffer = new byte[4];
int read = stream.Read (sizeBuffer, 0, 4);
int size = BitConverter.ToInt32 (sizeBuffer, 0);
Databaser.log ("recieved byte message denoting size: " + size);
byte[] messageBuffer = new byte[size];
read = stream.Read (messageBuffer, 0, size);
string result = BitConverter.ToString (messageBuffer);
Databaser.log ("\tmessage is as follows: '" + result + "'");
Where, if it's not evident from the code, the client sends 4 bytes, which are combined into a 32 bit integer which is the length of the message. Then I read in the message based on that length and have build in converters translate it into a string.
As I said, I'm wondering how to flush the connection? I know this code isn't perfect, but I can change it back to when I used TCP and UTF exclusive string messaging over the network, but either way, the connection doesn't send anything from the client until the client shuts down or closes the connection.
Maybe the problem is in the byte order. I have an application which send from a tablet (java) to a C# application (Windows Intel), I used similar to what you've done, except in the following
ByteBuffer iLength = ByteBuffer.allocate(4);
iLength.order(ByteOrder.LITTLE_ENDIAN);
iLength.putInt(length);
output.write(iLength.array(), 0, 4);
output.write(buffer);
output.flush();
Java uses BIG-ENDIAN and Intel uses LITTLE-ENDIAN bytes order.
I want to connect Android Device to external device via Socket. Socket Connect to external device successfully.
Now if any data require from external device then send request of byte packet data to socket below order. if external device receive data correct then send byte data in response.
Parameters : methodname(1 byte), payloadlength(2 byte), payload(2 byte).
Now My Code is...
Socket socket = new Socket("local exteranl device ip", 5000);
if(socket.isConnected()) {
int methodname = 5;
int payload = 2151;
int payloadLength = 2;
ByteBuffer buffer = ByteBuffer.allocate(3 + payloadLength); // 3 = for method name + length
buffer.order(ByteOrder.BIG_ENDIAN); // Just to be explicit
buffer.put((byte) methodname);
buffer.putShort((short) payloadLength);
buffer.putShort((short) payload);
buffer.rewind();
byte[] result = new byte[buffer.capacity()]; // Could also use result = buffer.array();
buffer.get(result);
DataOutputStream classOUTstream = new DataOutputStream(socket.getOutputStream());
// socket is already connected
classOUTstream.write(result);
classOUTstream.flush();
InputStream stream = socket.getInputStream();
byte[] data = new byte[100];
int count = stream.read(data);
}
Above Code is Android, i knowing only basic concept of java. i am getting -1 result in count.
can any one please suggest me or tell me my mistake?
You're doing this the hard way. Get rid of the ByteBuffer altogether and use all the methods of DataOutputStream. They are all big-endian. I can't see any mistake but clearly you must be sending something the peer didn't understand so he is closing the connection instead of sending a reply.
Note: Socket.isConnected() cannot possibly be false at the point you're testing it.
I am sending data to a server in two steps:
1) Length of what I will send using byte[4]
2) Data.
The server listens to the exact length of the data (shipped first) and then replies.
So I listen to the InputStream and try to get the data.
My Problem:
Whatever I am doing I am getting only the stream I send, but the server definatly sends a new string.
It seems I cannot wait for a -1 (end of string), as the program would time out and I am sure the server does not send anything alike.
Therefore I am using inputStream.available() to find out how many bytes are left in the buffer.
Once I am sending inputStream.read() after reading all the data it will time out with "Network idle timeout".
But I need to listen to the inputStream to make sure I am not missing information.
Why am I only receiving the information I send and not what is send by the server?
How can I listen to the connection for new items coming in?
Here is my code:
private void sendData (byte[] sendBytes){
try {
os.write(sendBytes);
os.flush();
} catch (IOException ex) {
}
}
Please help
THD
This is how you normally read all data from a reader (until the other end closes):
//BufferedReader is
StringBuilder data = new StringBuilder();
char[] buffer = new char[1024 * 32];
int len = 0;
while ((len = is.read(buffer)) != -1) {
data.append(buffer, 0, len);
}
//data will on this line contain all code received from the server