Client Sending Big String (BASE64 Image) from server to client - java

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 ();
}
}

Related

Sending Unicast packets to a Multicast port

I have a Multicast socket open and is receiving Multicast message. From this thread, it seems that the same multicast socket should also be able to receive unicast messages. However, I'm not able to get anything.
Edit: the port number seems the be problem. Port 3702 is used by ws-discovery for unicasting which is related to what I'm trying to do. I'm tracking down a problem where the client's probe to the service is not caught by the service's multicast socket. I'm running this on windows.
My multicast server:
class Server extends Thread {
MulticastSocket multicastSocket;
final Logger LOG;
final int PORT = 3702;
final String MULTICAST_ADDR = "239.255.255.250";
InetAddress multicastGroup;
public Server() {
LOG = Logger.getLogger("Server");
try {
multicastGroup = InetAddress.getByName(MULTICAST_ADDR);
multicastSocket = new MulticastSocket(PORT);
multicastSocket.setInterface(InetAddress.getLocalHost());
multicastSocket.joinGroup(multicastGroup);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
while (!Global.exit) {
byte[] buf = new byte[1000];
DatagramPacket recv = new DatagramPacket(buf, buf.length);
try {
multicastSocket.receive(recv);
String msg = new String(recv.getData(), StandardCharsets.UTF_8);
LOG.log(Level.INFO, "got: " + msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
And the client code:
public void directMsgTest(){
try {
DatagramSocket datagramSocket = new DatagramSocket( 8080,InetAddress.getLocalHost());
String msg = "direct msg";
byte[] buf = msg.getBytes();
DatagramPacket packet = new DatagramPacket(buf, buf.length, InetAddress.getLocalHost(), DST_PORT);
datagramSocket.send(packet);
datagramSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
It seems that this is Window's fault. It uses WS discovery in some of its services, thus using port 3702 and eating unicast packets send to port 3702 instead of giving it to my server.
I tried running this on Linux and it was fine.

Facilitate High availability cluster(HAC) in Java

For my class project I have the following problem. I am able to receive client information and re-send the info to the respective client. However, I am not being able to send every clients' info to every other client (Broadcast?). I also need to implement the given functions. Any help would be appreciated.
The goal is to design and implement a simple application layer protocol over UDP to
facilitate High Availability Cluster (HAC). HAC has a set of mechanism to detect failovers,
network/node failure etc. in order to re-route the traffic to the available systems. In this project
you will not be working on the questions like how to perform consistent failover, or high
availability distributed hypervisor. However, your task is to design and implement a protocol to
maintain the up-node information throughout the cluster.
Your designed protocol should perform the following functions:
a) To detect node failure periodically
b) To inform the other nodes in the network about the failure (peering option)
c) To be able to detect when the failed node comes back to life
d) To inform other nodes about the availability of new node
Client Class:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.*;
import java.util.Random;
public class UDPClient
{
DatagramSocket Socket;
public UDPClient()
{
}
public void createAndListenSocket() throws ClassNotFoundException, InterruptedException
{
try
{
Socket = new DatagramSocket();
InetAddress IPAddress = InetAddress.getByName("localhost");
byte[] incomingData = new byte[1024];
String sentence = "Client 1 is up";
byte[] data = sentence.getBytes();
boolean flag = true;
CreatePacket packet = new CreatePacket(data, flag, data.length);
while(true)
{
//Serialize to send
Random rnd = new Random();
int timeout = rnd.nextInt(30);
Thread.sleep(timeout*1000);
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(buffer);
out.writeObject(packet);
out.close();
buffer.close();
DatagramPacket sendPacket = new DatagramPacket(buffer.toByteArray(), buffer.size(), IPAddress, 9876);
Socket.send(sendPacket);
System.out.println("Message sent from client");
//Deserialize and receive packet from server
DatagramPacket incomingPacket = new DatagramPacket(incomingData, incomingData.length);
Socket.receive(incomingPacket);
ByteArrayInputStream bis = new ByteArrayInputStream(incomingPacket.getData());
ObjectInputStream in = new ObjectInputStream(bis);
Object receivedPacket = in.readObject();
in.close();
InetAddress IPAddress1 = incomingPacket.getAddress();
int port = incomingPacket.getPort();
System.out.println();
System.out.println("Response from server: ");
System.out.println("Message : " + receivedPacket.toString());
System.out.println("Client IP: "+ IPAddress1.getHostAddress());
System.out.println("Client port: "+ port);
}
}
catch (UnknownHostException e)
{
e.printStackTrace();
}
catch (SocketException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception
{
UDPClient client = new UDPClient();
client.createAndListenSocket();
}
}
Server code:
public class UDPServer
{
DatagramSocket socket = null;
public UDPServer()
{
}
public void createAndListenSocket() throws ClassNotFoundException
{
try
{
socket = new DatagramSocket(9876);
byte[] incomingData = new byte[1024];
while (true)
{
DatagramPacket incomingPacket = new DatagramPacket(incomingData, incomingData.length);
socket.receive(incomingPacket);
CreatePacket toSendPacket = new CreatePacket(incomingData, incomingData.length);
ArrayList <CreatePacket> clients = new ArrayList<CreatePacket>(4);
ByteArrayInputStream bis = new ByteArrayInputStream(incomingPacket.getData());
ObjectInputStream in = new ObjectInputStream(bis);
Object receivedPacket = in.readObject();
in.close();
clients.add(toSendPacket);
InetAddress IPAddress = incomingPacket.getAddress();
int port = incomingPacket.getPort();
System.out.println();
System.out.println("" + receivedPacket.toString());
System.out.println("Client IP: "+ IPAddress.getHostAddress());
System.out.println("Client port: "+ port);
DatagramPacket replyPacket = new DatagramPacket(incomingData, incomingData.length, IPAddress, port);
Thread.sleep(10*1000);
socket.send(replyPacket);
//socket.close();
}
}
catch (SocketException e)
{
e.printStackTrace();
}
catch (IOException i)
{
i.printStackTrace();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
public static void main(String[] args) throws ClassNotFoundException, IOException
{
UDPServer server = new UDPServer();
server.createAndListenSocket();
}
}
You want
1 - client to send message to server if it is up/alive
2 - and for server to send some message to all client if it receives signal right?
I am not sure but you can try this,
InetAddress IPAddress = incomingPacket.getAddress();
int port = incomingPacket.getPort();
as you are getting IP address of one client you can store address of all clients on server side which are up/alive in a List or array. Then if you receives signal to server use that list to send respond.
You will need to update list according to up/alive clients.

Why I can't view my UDP received Image in Android Studio?

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]

Why does UDP part of RTSP client/server work locally but not remotely? [Java]

I made a simple RTSP program (Client and Server) in java to stream audio from an input device to a single client. I tried it locally and it works fine. Then I tried a remote client test and it fails. The the ServerSocket accepts the remote client connection and I can see/get the remote IP using the getInetAddress() method but the UDP part of the program seem to not work as expected.
Here is my code.
Code listing-1: RTSPServer.java
//imports go here
public class RTSPServer {
public static void main(String args[]) {
RTSPServer server = new RTSPServer();
try {
server.connect(9091);
} catch (IOException ex) {
Logger.getLogger(RTSPServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void connect(int port) throws IOException{
try (ServerSocket listener = new ServerSocket(port)) {
while (true) {
try (Socket clientSocket = listener.accept()) {
//--------RTSP starts tests here---------
//--------RTSP ends tests here---------
//--------UDP streaming starts here---------
System.out.println(clientSocket.getInetAddress());//print the IP address for debugging purpose
DatagramSocket RTSPsocket = new DatagramSocket(8300); //socket for send and receive
RTSPsocket.setSoTimeout(800);//timeout set # 800ms because ping from VPN server to home > 680ms
DatagramPacket udpPacket;
//InetAddress ClientIPAddr = InetAddress.getLocalHost();//getLocalHost version works locally
InetAddress ClientIPAddr = clientSocket.getInetAddress();//getInetAddress doesn't work locally and remotely
//InetAddress ClientIPAddr = clientSocket.getLocalAddress();//getLocalAddress only works locally
AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100, 16, 2, 4, 44100, false);
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
TargetDataLine targetLine = (TargetDataLine)AudioSystem.getLine(info);
targetLine.open(format, 40000);
targetLine.start();
byte[] data = new byte[targetLine.getBufferSize()/5];
while(true){
targetLine.read(data, 0, data.length);
RTPPacket rtpPacket = new RTPPacket(0, 0, 0, data, data.length);//make an RTP packet out of the targeLine data
//retrieve the packet bitstream and store it in an array of bytes
byte[] packetBytesArray = new byte[rtpPacket.getlength()];
rtpPacket.getpacket(packetBytesArray);
//send the RTP packet over the UDP socket using datagram packet
udpPacket = new DatagramPacket(packetBytesArray, packetBytesArray.length, ClientIPAddr, 8550);
RTSPsocket.send(udpPacket);
}
} catch (LineUnavailableException ex) {
Logger.getLogger(RTSPServer.class.getName()).log(Level.SEVERE, null, ex);
}
//--------UDP streaming ends here---------
}
} catch (IOException ex) {
Logger.getLogger(RTSPServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Code listing-1: RTSPClient.java
public class RTSPClient {
//imports go here
private Socket clientSocket;
private int port;
private String address;
public static void main(String argv[]) throws Exception
{
RTSPClient client = new RTSPClient("my.ip.address.here",9091);
client.connect();
}
public RTSPClient(String address, int port){
this.port = port;
this.address = address;
}
public void connect() throws IOException {
clientSocket = new Socket(address, port);
DatagramSocket udpSocket = null; //socket for send and receive
DatagramPacket udpPacket; //UDP packet used to receive packet
int RTSP_RCV_PORT = 8550; //receiving port for UDP/RTSP
byte[] buf = new byte[8000]; //buffer used to store data received from the server
try{
udpSocket = new DatagramSocket(RTSP_RCV_PORT);
udpSocket.setSoTimeout(40);//socket timeout 40ms
}
catch (SocketException ex)
{
System.exit(0);
}
//--------RTSP starts tests here---------
//--------RTSP ends tests here---------
//--------UDP streaming starts here---------
AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100, 16, 2, 4, 44100, false);
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
SourceDataLine sourceLine = null;
try {
sourceLine = (SourceDataLine)AudioSystem.getLine(info);
sourceLine.open();
} catch (LineUnavailableException ex) {
Logger.getLogger(RTSPClient.class.getName()).log(Level.SEVERE, null, ex);
}
if(sourceLine != null){
sourceLine.start();
boolean makeMeLoop = true;
while(makeMeLoop){
udpPacket = new DatagramPacket(buf, buf.length);
try{
//* receive the DP from the socket:
udpSocket.receive(udpPacket);
//* create an RTPpacket object from the DP
RTPPacket rtp_packet = new RTPPacket(udpPacket.getData(), udpPacket.getLength());
//* print important header fields of the RTP packet received:
System.out.println("Got RTP packet");
//* get the payload bitstream from the RTPpacket object
int payload_length = rtp_packet.getpayload_length();
byte [] payload = new byte[payload_length];
rtp_packet.getpayload(payload);
sourceLine.write(payload, 0, payload.length);
}
catch (InterruptedIOException ex){
System.out.println("Nothing received");
}
catch (IOException ex) {
System.out.println("Exception caught: "+ex);
}
}
}
clientSocket.close();
}
}
Since the classes are huge I only left the part of the code that is necessary to troubleshoot the program.
How I've done my remote client test
I ran both code on the same physical machine but the client ran on a virtual machine connected to a VPN proxy. I increased the socket timeout for the RTSPServer's UDP socket because the ping between the VPN server's location and a test server near my location (speedtest.net) was close to 700ms (I am not sure if doing that was relevant).
When I connect the remote client to the server the server gives me the remote client's IP address (same address as given in whatismyipaddress.com). So the client is actually connected to the server. But when it comes to send the audio stream, I only get Nothing received messages. Also my computer can be accessed remotely (obviously because the client was able to connect to the server) and every port should be "visible" outside of my LAN (web server can also be accessed, and so on for every ports I've tried).

C# server Socket to Android Socket over NAT

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);
}

Categories