I succeeded in sending a string from Android Studio Java UDP Client to Visual Studio C# UDP Server, and a response back from the Server to the Client.
Now I am trying to send an Image back from the server instead of a string response. So on client button click, I am supposed to get an Image back from the server. No syntax errors and no weird behavior. It's just nothing happens and I can't seem to see the received image on my ImageView and when I step over it my final Bitmap ReceivedImage is null
Do I need to convert into something other than Bitmap? Is this the right way? Maybe something else.. Can anyone help me point out my mistake? Thanks
C# Server:
class UdpServer
{
static void Main(string[] args)
{
byte[] dataReceived = new byte[1024];
UdpClient serverSocket = new UdpClient(15000);
string path = "C:\\Users\\kkhalaf\\Desktop\\Capture.PNG"; // image path
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read); // prepare
BinaryReader br = new BinaryReader(fs); // prepare
byte[] dataToSend = br.ReadBytes(Convert.ToInt16(fs.Length)); //Convert image to byte[]
int i = 0;
while (true) // this while for keeping the server "listening"
{
Console.WriteLine("Waiting for a UDP client..."); // display stuff
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0); // prepare
dataReceived = serverSocket.Receive(ref sender); // receive packet
string stringData = Encoding.ASCII.GetString(dataReceived, 0, dataReceived.Length); // get string from packet
Console.WriteLine("Response from " + sender.Address); // display stuff
Console.WriteLine("Message " + i++ + ": " + stringData + "\n"); // display client's string
// Here I am sending back
serverSocket.Send(dataToSend, 8, sender);
}
}
}
Java Client: On button click this function gets called to send-receive-display
public void SendUdpMsg(final String msg)
{
Thread networkThread = new Thread() {
// No local Host 127.0.0.1 in Android
String host = "192.168.200.3"; // Server's IP
int port = 15000;
DatagramSocket dsocket = null;
public void run() {
try {
// Get the Internet address of the specified host
InetAddress address = InetAddress.getByName(host);
// wrap a packet
DatagramPacket packetToSend = new DatagramPacket(
msg.getBytes(),
msg.length(),
address, port);
// Create a datagram socket, send the packet through it.
dsocket = new DatagramSocket();
dsocket.send(packetToSend);
// Here, I am receiving the response
byte[] buffer = new byte[1024]; // prepare
DatagramPacket packetReceived = new DatagramPacket(buffer, buffer.length); // prepare
dsocket.receive(packetReceived); // receive packet
byte[] buff = packetReceived.getData(); // convert packet to byte[]
final Bitmap ReceivedImage = BitmapFactory.decodeByteArray(buff, 0, buff.length); // convert byte[] to image
runOnUiThread(new Runnable() {
#Override
public void run() {
// this is executed on the main (UI) thread
final ImageView imageView = (ImageView) findViewById(R.id.imageView);
imageView.setImageBitmap(ReceivedImage);
}
});
dsocket.close();
} catch (Exception e) {
e.printStackTrace();
}//catch
}//run
};// Networkthread
networkThread.start();//networkThread.start()
}
Isn't much of an answer, but since I can't comments yolo
You should use TCP, it is so much better. Using UDP, I even loose data when it is 400 bytes.
It might be
serverSocket.Send(dataToSend, 8, sender);
Change it to
serverSocket.Send(dataToSend, dataToSend.Length, sender);
Also, try first sending the length of the image (dataToSend.Length) to the client, then have the client use the length you sent it to create a byte array. Kind like
byte[] buffer = new byte[recievedLengthOfImage]
Related
Currently I am working on a performance testing tool and I have to develop a UDP request testing plugin for load testing. I tried to send continuous large number of request to monitor the maximum load that server could handle. My goal is to make the application not responsive by sending maximum number of requests but i am not getting the expected result. My testing application is up and running in my local environment. Is it the fault of the implementation or the configurations. Please help.
//UDPRequests.groovy
package com.udp.testsubject;
import java.security.SecureRandom;
public class UDPRequests {
static void main(String [] args) {
DatagramSocket socket = null;
InetAddress address = null;
byte[] buf = new byte[65507];
SecureRandom random = new SecureRandom();
//following paramters will get from a property file
String ipAddr = '127.0.0.1';
int portDst = 4445;
int numberOfRequests = 1200000;
socket = new DatagramSocket();
address = InetAddress.getByName(ipAddr);
random.nextBytes(buf);
DatagramPacket packet = new DatagramPacket(buf, buf.length, address, portDst);
try {
printf("[*] Start send requests to %s:%d\n", ipAddr, portDst);
int count=0;
while (count < numberOfRequests) {
count++;
socket.send(packet);
}
} catch (IOException e) {
e.printStackTrace();
}
socket.close();
}
}
I'm writing an android source(but just java) to communicate with some embedded device which acts as a server.
I am sure that my UDP datagrams are arriving to the device since I can observe the device state changing.
But the problem is that I am failing to get response from the server. Not receiving nothing, but I just get an echo of what I sent. My source is as below.
public void sendSnapShot(View view) {
//send a udp datagram to the server.
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... voids) {
try {
Log.e("Test", "send sendSnapShot onLine");
DatagramSocket clientSocket = new DatagramSocket();
byte[] sendData = new byte[1024];
String sentence = "$SNAPSHOT";
sendData = sentence.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, InetAddress.getByName("192.168.5.255"), 9999);
clientSocket.send(sendPacket);
Log.e("Test", "Sent sendSnapShot REQUEST");
} catch (Exception e) {
Log.e("Test", "e", e);
}
return null;
}
}.execute();
}
The above code is about transfering datagram to the server. On the start of the application, the below thread will be started to listen for any datagram sent by the server.
private class ListenerThread implements Runnable {
//listen for incoming datagrams.
#Override
public void run() {
DatagramSocket serverSocket = null;
try {
InetAddress serverAddr = InetAddress.getByName("192.168.5.255");
serverSocket = new DatagramSocket(9999, serverAddr);
while (true) {
try {
byte[] receiveData = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
receivePacket.getLength();
String receivedData = new String(receivePacket.getData(), 0, receivePacket.getLength());
if (!receivedData.startsWith("!HEARTBEAT")) {
Log.e("Test", "Received : " + receivedData);
} else {
Log.e("Test", "Received : HEARTBEAT");
}
} catch (Exception e) {
Log.e("Test", "FROM SERVER ", e);
}
}
} catch (Exception e) {
Log.e("Test", "Exception", e);
}
}
}
The guy who wrote the server code(probably written in c++) says that he is getting response in his test case, so what may I be missing? Is there a possiblity that the above code will ignore any datagram from the server and echo bytes sent from my code?
=============================================================================
I've changed my code according to the answer. I no longer use the listening thread anymore. Here's my code.
public void sendBattery(View view) {
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... voids) {
try {
Log.e("Test", "send Battery onLine");
DatagramSocket clientSocket = new DatagramSocket(9999, InetAddress.getByName("0.0.0.0"));
byte[] sendData = new byte[1024];
byte[] receivedata = new byte[1024];
String sentence = "$S0B255";
DatagramPacket receivePacket = new DatagramPacket(receivedata, receivedata.length);
sendData = sentence.getBytes();
String receivedData = " ";
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, InetAddress.getByName("192.168.5.1"), 9999);
clientSocket.send(sendPacket);
do{
clientSocket.receive(receivePacket);
receivedData = new String(receivePacket.getData(), 0, receivePacket.getLength());
Log.e("Test", receivedData + ", IP CHECK Sender: : " + receivePacket.getAddress().toString() + ", port : "+ receivePacket.getPort());
}while(true);
// Log.e("Test", "Sent BATTERY REQUEST COMPL");
} catch (Exception e) {
Log.e("Test", "e", e);
}
return null;
}
}.execute();
}
According to the heartbeat byte(making it to a string will make it "!HEARTBEAT") i'm receiving, the sender is 192.168.5.1. But still, I only get heartbeat bytes only. What shall I be missing?
You are receiving your own datagrams, because you are broadcasting (to 192.168.5.255). You should use the device's actual IP address.
You should not create a new datagram socket per send. (You are never closing that socket, so you are also leaking sockets.)
You should send the datagrams from the same socket you are receiving on. The device will (should) reply to the IP:port the request came from, and at present that's different every time, and you're losing the sending socket that's bound to that port, and the sending IP:port isn't the IP:port you're listening on, so you don't hear it.
You should not bind your listening socket to a specific IP address, and certainly not to a broadcast address. I'm surprised it works.
What EJP was saying was right about everything.
The fixed code above(the most below code snippet) which included tips from him will work, without having to receive any broadcast by myself.
I thought the issue was unresolved since I still didn't get any response from the device, but it was the device(not made by me) which was malfunctioning. The above code will work good.
I have a problem in communication between client and server through socket.
Java server and the client in C#. When I send a String Base64 type image to my C# client my program crashes because of the size of string.
void ecouteur(string commande) {
try {
IPEndPoint ip = new IPEndPoint (IPAddress.Parse ("127.0.0.1"), 1234);
System.Net.Sockets.Socket sock = new System.Net.Sockets.Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sock.Connect (ip);
byte[] data = new byte[2024];
int receivedDataLength = sock.Receive (data);
String temp = Base64Decode( Encoding.ASCII.GetString (data, 0, receivedDataLength));
sock.Shutdown (SocketShutdown.Both);
sock.Close ();
} catch (SocketException e1) {
Console.WriteLine ("****Unable to connect to server.****\n" + e1);
//sock.Shutdown (SocketShutdown.Both);
sock.Close ();
}
}
The Android app is behind a NAT (3G connection) , while the server is on a public IP.
The Android app can connect to the server socket and send data (via Socket/TCPclient on android) but the server cannot connect to the Android port because of the NATs
(server getting "... has failed to respond "ip_adress_of_android : port_that_is_open_and_listening_on_android".
Is there anyway to overcome this, or some parameters I can use in order for the server connection attempt to reach it's destination over the NATs without using a custom library? - or could you please point me to an easy to implement method, I don't have time to study and integrate a complicated 3rd party library
Here is a sample of how my server code works:
int port_server, port_android; // used to declare used ports by the server and android
Socket server_socket, client_socket; //sockets used to receive and send data
server_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server_socket.Bind(new IPEndPoint(IPAddress.Any, port_server));
server_socket.Listen(0);
public void listen()
{
server_socket.BeginAccept(new AsyncCallback(AcceptCallback), null);
}
private void AcceptCallback(IAsyncResult AR)
{
client_socket = server_socket.EndAccept(AR);
buffer = new byte[client_socket.ReceiveBufferSize];
client_socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);
}
private void ReceiveCallback(IAsyncResult AR)
{
listen(); // to continue listening to the port
// code that does something with the data
send_string("Take this"); // sends a string to android
}
public void send_string(string notif)
{
string ip_client = client_socket.RemoteEndPoint.ToString();
string ip_client2 = (ip_c.Split(':'))[0];
TcpClient client = new TcpClient(ip_client, port_android);
Byte[] notifi = System.Text.Encoding.ASCII.GetBytes(notif);
NetworkStream stream = client.GetStream();
stream.Write(notifi, 0, notifi.Length);
stream.Close();
client.Close();
}
I should note that they work both ways when on a LAN, so the code is working, I only need to modify is so that it can reach android targets over NATs.
Something like this
class Program
{
int port_server = 42424;
Socket server_socket;
public Program()
{
server_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server_socket.Bind(new IPEndPoint(IPAddress.Any, port_server));
server_socket.Listen(0);
}
public void Listen()
{
while (true)
{
var client = server_socket.Accept();
var buffer = new byte[client.ReceiveBufferSize];
client.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), Tuple.Create(client, buffer));
}
}
private void ReceiveCallback(IAsyncResult AR)
{
var state = (Tuple<Socket, byte[]>)AR.AsyncState;
var client = state.Item1;
var buffer = state.Item2;
byte[] notifi = System.Text.Encoding.ASCII.GetBytes("Take this");
client.Send(notifi);
client.Close();
}
static void Main(string[] args)
{
var programm = new Program();
programm.Listen();
}
}
client part
using (Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
client.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 42424));
client.Send(new byte[] {1, 2, 3}, SocketFlags.None);
byte[] bt = new byte[256];
client.Receive(bt, 256, SocketFlags.None);
}
Is it possible to use a single DatagramSocket to send and receive packets in a single Java application? I have been attempting to do this using threads but have had not luck. Every socket tutorial I find online uses separate client and server classes to send data. However, in my case, I want the client and server to reside in a single application. Below is my attempt:
public class Main implements Runnable {
// global variables
static DatagramSocket sock;
String globalAddress = "148.61.112.104";
int portNumber = 9876;
byte[] receiveData = new byte[1024];
public static void main(String[] args) throws IOException {
sock = new DatagramSocket();
(new Thread(new Main())).start();
// send data
while (true) {
InetAddress IPAddress = InetAddress.getByName("127.0.0.1");
int port = 9876;
int length = 1024;
byte [] sendData = new byte[1024];
String message = "hello";
sendData = message.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length,
IPAddress, port);
sock.send(sendPacket);
}
}
public void run() {
//get incoming data
while (true) {
byte[] sendData = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(receiveData,
receiveData.length);
receivePacket.setPort(portNumber);
try {
sock.receive(receivePacket);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String sentence = new String(receivePacket.getData());
System.out.println("RECEIVED: " + sentence);
}
}
}
As you can see I am sending data in a loop on the main thread and receiving data on the loop in the runnable thread. The main thread should continuously send "hello" to the receiver and output the message. However, no output is given?
Am I on the right track here? Is using threads the best way to do this? Is this even possible? And if so is there a better solution?