Android - Send and receive byte - java

I've a tcp connection and i try to send and receive messages in byte, but I don't know how it work.
Here is my code to send:
public void write(String message) {
try {
byte[] b = message.getBytes("UTF-8");
writer.write(b.toString());
writer.newLine();
writer.flush();
} catch (IOException e) {
Log.e(MainActivity.TAG, "exception", e);
e.printStackTrace();
} catch (Exception e) {
Log.e(MainActivity.TAG, "exception", e);
e.printStackTrace();
}
}
and this for receive
String message = client.reader.readLine();
JSONObject json = new JSONObject(message);
I try again :)
How I can convert the received byte array to string with full unicode for the mysql database? I use charset Utf8m4 for my database.
This is my code
byte[] message = System.Text.Encoding.UTF8.GetBytes(client.reader.ReadLine()); // client.reader.ReadLine() is already a byte[]
string encoded = System.Text.Encoding.UTF8.GetString(message);
JToken token = JObject.Parse(encoded);
My code isn't work. I get:
{"Id":"Test","Content":"hey???"}

byte[] b = message.getBytes("UTF-8");
writer.write(b.toString());
If this is the code you're asking abut, it is senseless. It should of course be
writer.write(message);
At present you're sending something of the form [B#NNNNNNNNNNN, which is the hashcode of a byte array.

I've found a solution, thank's to #EJP.
In java (client side)
writer.write(B64.encode(message)); // message is a string
In C# (server side)
string encoded = System.Text.Encoding.UTF8.GetString(message);
JToken token = JObject.Parse(encoded);
To save the bytes in database i use blob as type.
Encoding.UTF8.GetBytes(bluuub)
To get the bytes from database
byte[] b = (byte[])reader.GetValue(0);
string bluuub = Encoding.UTF8.GetString(b);

Related

Send DHT queries to "router.bittorrent.com" response garbled text

I read the DHT Protocol in bep_0005 page.
But when I send a ping query or a find_node query, the server response a garbled text (both of router.bittorrent.com:6881 or dht.transmissionbt.com:6881)
Here is the Java source code bellow
public String ping(final String id) {
System.out.println("Start ping:" + id);
Bencode bencode = new Bencode();
byte[] encoded = bencode.encode(new HashMap<Object, Object>() {
private static final long serialVersionUID = 4225164001818744013L;
{
put("t", "tr");
put("y", "q");
put("q", "ping");
put("a", new HashMap<Object, Object>() {
private static final long serialVersionUID = -6092073963971093460L;
{
put("id", id);
}
});
}
});
byte[] result = client.send(new String(encoded, bencode.getCharset()));
Map<String, Object> dict = bencode.decode(result, Type.DICTIONARY);
System.out.println("Bdecoded Data:" + dict);
return "";
}
Send Packets
ping Query = {"t":"aa", "y":"q", "q":"ping", "a":{"id":"abcdefghij0123456789"}}
bencoded = d1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe
Acrodding to the bep_0005 protocol the response with be like:
Response = {"t":"aa", "y":"r", "r": {"id":"mnopqrstuvwxyz123456"}}
bencoded = d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re
But my response is:
Response = {ip=��P���, r={id=2�NisQ�J�)ͺ����F|�g}, t=tr, y=r}
bencoded = d2:ip6:��P���1:rd2:id20:2�NisQ�J�)ͺ����F|�ge1:t2:tr1:y1:re
Send udp part Java code is:
public byte[] send(String sendData) {
DatagramSocket client;
try {
client = new DatagramSocket();
client.setSoTimeout(5000);
byte[] sendBuffer;
sendBuffer = sendData.getBytes();
InetAddress addr = InetAddress.getByName("router.bittorrent.com");
int port = 6881;
DatagramPacket sendPacket = new DatagramPacket(sendBuffer, sendBuffer.length, addr, port);
client.send(sendPacket);
byte[] receiveBuf = new byte[512];
DatagramPacket receivePacket = new DatagramPacket(receiveBuf, receiveBuf.length);
client.receive(receivePacket);
System.out.println("Client Source Data:" + Arrays.toString(receivePacket.getData()));
String receiveData = new String(receivePacket.getData(), "UTF-8");
System.out.println("Client String Data:" + receiveData);
client.close();
return receivePacket.getData();
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
read the response in UTF-8 , but the iso-8859-1 is also a garbled text.
who can help me,thanks!
the server response a garbled text
No, the response is bencoded and contains raw binary data.
It CAN NOT be treated as text.
In BEP5, to make the raw binary node_id in the examples printable,
it has cleverly been chosen to consist of only alphanumeric characters.
See:
Bittorrent KRPC - Why are node ID's half the size of an info_hash and use every character a-z?
The ip key is a extension explained in: BEP42 - DHT Security extension
The received response is fully valid.
TODO: Working Java code
Map<String, Object> dict = bencode.decode(result, Type.DICTIONARY);
This gives you the decoded root dictionary of the message as Map. Within that you should find the r dictionary as another map and with in that map the id value. What type the id has will depend on the bedecoding library you are using.
If it is ByteBuffer or byte[] then you should have 20 bytes that you can hexencode (to 40 characters) if you need it to be human-readable. The DHT protocol deals in raw hashes, not hex values.
If it is a String then you will have to convert the string back into byte[] before hex-encoding it. That is only possible when the bdecoder used ISO 8859-1 to decode because that charset is roundtrip-safe while utf-8 is not for arbitrary byte sequences.

Get array from socket

I'm finding a way to get an array, each component can have value between 0 and 255.
I'm using Android Studio and I received data from a socket. The following is my code.
try {
InetAddress IpAddress = InetAddress.getByName(remoteName);
myUpd_socket = new DatagramSocket(remotePort);
// Send connect message
String str = "connect request";
send_data = str.getBytes();
DatagramPacket send_packet = new DatagramPacket(send_data,str.length(), IpAddress, remotePort);
myUpd_socket.send(send_packet);
byte[] dataArray = new byte[1024];
DatagramPacket udp_packet = new DatagramPacket(dataArray,dataArray.length);
while (true) {
myUpd_socket.receive(udp_packet);
byte[] buff = new byte[udp_packet.getLength()];
System.arraycopy(dataArray,0,buff,0,buff.length);
}
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
I need to get the same data from the transmitter. There is no negative value in original data. But when I checked the received data, the buff has a lot of negative values. I made something wrong here.
I'm a newbie of Java and android. So I'm really grateful if someone can help me.
Thank.
Why not to use:
RECEIVE
Socket socket = ...
DataInputStream in = new DataInputStream(socket.getInputStream());
int length = in.readInt(); // read length of incoming message
if(length>0) {
byte[] message = new byte[length];
in.readFully(message, 0, message.length); // read the message
}
SEND
byte[] message = ...
Socket socket = ...
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeInt(message.length); // write length of the message
out.write(message); // write the message
bytes are signed in Java. If you want the unsigned value (as an int), use this: byteValue & 0xFF.

Android - huge data in Base 64, how to handle it

I have a web service, which gives me a json having a node named as 'imagedata'. It contains a huge data as a string. When I print this in browser it gives me valid input. Base64 encoded strings ends on '=' character.
I have also tested it using this tag in a html page, and it works perfectly fine.
<img src="data:image/png;base64,MY_BASE64_ENCODED_STRING"/>
Here is my code;
StringBuilder b64 = new StringBuilder(dataObj.getString("imagedata"));
byte[] decodedByte = Base64.decode(b64.toString(), 0);
bitmap = BitmapFactory.decodeByteArray(decodedByte, 0, decodedByte.length);
Kindly note that, This code works on smaller image-data but gives bad-base64 exception on larger image-data
Kindly help me out,
Thanks
Why your server give you the base64 encoding?. Base64 it is just communication not to encoding image. If it use for encoding it will make your image file size bigger.IllegalArgumentException mean your image encoding incorrectly formatted or otherwise cannot be decoded.
In my project i just, for now, i use the Base64 for sending image. But it will be change by multipart. But when server forward to the recipient. It just forward the url of image. So i can do simple process the url to Image with this:
public static Image loadImage(String url)
{
HttpConnection connection = null;
DataInputStream dis = null;
byte[] data = null;
try
{
connection = (HttpConnection) Connector.open(url);
int length = (int) connection.getLength();
data = new byte[length];
dis = new DataInputStream(connection.openInputStream());
dis.readFully(data);
}
catch (Exception e)
{
System.out.println("Error LoadImage: " + e.getMessage());
e.printStackTrace();
}
finally
{
if (connection != null)
try
{
connection.close();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
if (dis != null)
try
{
dis.close();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return Image.createImage(data, 0, data.length);
}
Note this code for J2ME.

Sending data from Java to C using socket programming

i am making a program that sends a string from a Java client to a C server using WinSock2. I am using DataOutputStream to send the data through the socket.
The C server, acknowledges the bytes received, but when i try accessing the data, nothing is displayed.
SERVER
Socket socket = null;
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream = null;
try {
socket = new Socket("10.40.0.86", 2007);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
//dataOutputStream.writeUTF("How are you doing let us see what is the maximum possible length that can be supported by the protocal");
String line = "hey";
dataOutputStream.writeUTF(line);
dataOutputStream.flush();
//System.out.println(dataInputStream.readLine());
System.out.println((String)dataInputStream.readLine().replaceAll("[^0-9]",""));
//System.out.println(dataInputStream.readInt());
//System.out.println(dataInputStream.readUTF());
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
CLIENT
if (socket_type != SOCK_DGRAM)
{
retval = recv(msgsock, Buffer, sizeof(Buffer), 0);
printf("Server: Received datagram from %s\n", inet_ntoa(from.sin_addr));
}
output
Server: Received 5 bytes, data "" from client
BUFFER :
Server: Echoing the same data back to client...
BUFFER :
Server: send() is OK.
Your C code needs to understand the data format written by writeUTF() (see the Javadoc), or else more simply you need to use write(char[]) or write(byte[]) at the Java end.
Here is how I solved this :-)
dataOutputStream.write(line.getBytes());
Or to be more specific here is my code:
out.write(("Hello from " + client.getLocalSocketAddress()).getBytes());

Can't get Java and C# to communicate through sockets

I've been trying to create a Java and C# app that would communicate together. In this case the user sends a String from the C# side, it should display on the Java console and echo back. Unfortunately, I have only been able to establish the connection, without being able to send or receive anything.
Java code snippet:
public CommunicationThreadHandler(Socket socket, CarList carList) {
this.socket = socket;
this.carList = carList;
try {
this.in = new DataInputStream(socket.getInputStream());
this.out = new DataOutputStream(socket.getOutputStream());
this.writer = new Writer(out);
} catch (IOException e) {
System.out.println("Exception when reading or receiving data!");
e.printStackTrace();
}
this.ip = socket.getRemoteSocketAddress().toString();
}
#Override
public void run() {
while (true) {
try {
Gson gson = new Gson();
String msgJson = in.readUTF();
String msg = gson.fromJson(msgJson,String.class);
System.out.println("Message from C# client: "+msg);
String reply = "Server echo: "+msg;
String replyJson = gson.toJson(reply);
out.writeUTF(replyJson);
if (msg.equals(Package.EXIT))
break;
} catch (IOException e) {
e.printStackTrace();
}
}
C# snippet:
public static void StartClient()
{
// Data buffer for incoming data.
byte[] bytes = new byte[1024];
// Connect to a remote device.
try
{
// Establish the remote endpoint for the socket.
// This example uses port 11000 on the local computer.
IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint remoteEP = new IPEndPoint(ipAddress, 11000);
// Create a TCP/IP socket.
Socket sender = new Socket(ipAddress.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
// Connect the socket to the remote endpoint. Catch any errors.
try
{
sender.Connect(remoteEP);
Console.WriteLine("Socket connected to {0}",
sender.RemoteEndPoint.ToString());
while (true)
{
Console.Write("Enter message to server: ");
string message = Console.ReadLine();
Console.WriteLine($"To be sent: {message}");
// Encode the data string into a byte array.
byte[] msg = Encoding.ASCII.GetBytes(message);
// Send the data through the socket.
int bytesSent = sender.Send(msg);
// Receive the response from the remote device.
int bytesRec = sender.Receive(bytes);
string msgFromServer = Encoding.ASCII.GetString(bytes, 0, bytesRec);
if (msgFromServer.Equals("EXIT"))
break;
Console.WriteLine($"Server says: {msgFromServer}");
}
// Release the socket.
sender.Shutdown(SocketShutdown.Both);
sender.Close();
}
Your problem is that you're using DataInputStream/DataOutputStream in Java, which use a Java-specific, XDR-like datatype serialization protocol. You are not using that protocol at your C# side.
Switching to using the raw input/output stream should be sufficient (although very brittle). However, notice that as you are sending raw bytes from C#, it will be impossible to tell for the recipient when the message is complete. It would be better to send the number of bytes of the message, followed by the actual message (this is what DataInputStream/DataOutputStream does, but it comes with additional considerations that you would need to correctly implement in your C# side, for example readUTF/writeUTF use a 'modified UTF-8' format instead of normal UTF-8).
The problem right now, is that you send raw bytes from C#, the readUTF() method reads the first two bytes as length, and then tries to read a message of that length. For example if C# sends "Hello" (encoded as 0x48, 0x65, 0x6c, 0x6c, 0x6f), then the Java side will read 0x48, 0x65 ("He") as "message length is 18533" and then tries to read 18533 bytes, while the actual remaining bytes are only 3 (the "llo"). This causes the input to block waiting for the remaining 18530 bytes, which never arrive.

Categories