I am trying to make a UDP Listener listening to a server and receiving data.
Here is the UDPListener :
public class UDPListener extends AsyncTask<Void, String, Void>{
public UDPConnector udpConnector;
public UDPListener(UDPConnector udpConnector){
byte[] buff;
this.udpConnector = udpConnector;
System.out.println("UDPListener initalized");
}
#Override
protected Void doInBackground(Void... voidResult){
Looper.prepare();
while(true){
byte[] buffer = new byte[512];
DatagramPacket p = new DatagramPacket(buffer, buffer.length);
try {
System.out.println("Message reçu debug ");
udpConnector.UDPSocket.receive(p);
if(p.getData().length > 0){
buffer = p.getData();
String s = new String(buffer, 0, p.getLength());
publishProgress(s);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
udpConnector.main.handleTextReceived(values[values.length-1]);
}
}
The problem is publishProgress() never gets executed. I am sure that the UDPConnector is well configured because i can send data to the server. And i know that the method doInBackground is executed. I am also sure that the serveur is sending data to me as i can receive it with other tools.
I can post more code if needed, please let me know.
Thanks
If you are using the phone emulator, the emulator might be changing your expected IP address for which you will have to create a redirect.
Look at this post
Datagram (UDP) receiver not working - not receiving broadcast packets
So, you don't initialize the socket with a specific port? which one is your server using for sending the datagrams? Maybe your problem is, that the socket is listening to a random port, which does not match to your port.
Related
I am trying to get my server made on vb.net to send messages to my client made on android. I have a client and server made on vb.net, I can send and receive messages (text) between them without problem. But when I try to make the client work the same on Android, I can not receive messages to the client (android), but if I could get it to send a message to the server (vb.net) .. They are stuck with this, and I do not understand how to continue
SERVER VB.NET
Imports System.Net.Sockets
Imports System.Text
Public Class Servidor
Dim Tcp As TcpListener
Dim th As New Threading.Thread(AddressOf Rutina)
Dim ejecuto = False
Private Sub Servidor_Load(sender As Object, e As EventArgs) Handles MyBase.Load
CheckForIllegalCrossThreadCalls = False
End Sub
Dim tcpservercliente As New TcpClient
Public Function Rutina()
Try
Do
If ejecuto = True Then
Exit Do
End If
If Tcp.Pending = True Then
tcpservercliente.Client = Tcp.AcceptSocket
End If
If tcpservercliente.Available > 0 Then
Dim databytes(1000) As Byte
Dim decode As New ASCIIEncoding
tcpservercliente.Client.Receive(databytes)
txtRecibido.Text += vbCrLf & "Cliente Android: " & decode.GetString(databytes)
End If
Loop
Catch ex As System.InvalidOperationException
MsgBox("Error: " & ex.Message)
End Try
End Function
Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
Try
Tcp = New TcpListener(System.Net.IPAddress.Parse("192.168.1.8"), 1371)
Tcp.Start()
th.Start()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Private Sub Servidor_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
th.Abort("Rutina")
Application.Exit()
End Sub
Private Sub btnEnviar_Click(sender As Object, e As EventArgs) Handles btnEnviar.Click
Try
Dim decode As New ASCIIEncoding
tcpservercliente.Client.Send(decode.GetBytes(txtMensajeEnviar.Text))
Catch ex As System.Net.Sockets.SocketException
MsgBox(ex.Message)
End Try
End Sub
CLIENT ANDROID
//CLASS RM
public class RM extends AsyncTask<Void, Void, Void> {
Socket socket;
BufferedReader input;
#Override
protected Void doInBackground(Void... voids) {
try {
socket = new Socket("192.168.1.8",1371);
InputStreamReader streamReader = new InputStreamReader(socket.getInputStream());
input = new BufferedReader(streamReader);
if(input.ready()){
Log.i("AsyncTask", "Ready ");
}else{
Log.i("AsyncTask", "No Ready");
}
input.close();
socket.close();
}catch (IOException e){
e.printStackTrace();
}
return null;
}
}
//VOID MAIN ACTIVITY
RM mr = new RM();
mr.execute();
The times I've tried to see that it returns, it's always empty. The message that is being sent from the server is not arriving
Sorry my bad english
==========================================
EDIT:
This is the class I use to send messages from the client (android) to the server (vb.net)
package com.example.app_test_client;
import android.os.AsyncTask;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
public class MessageSender extends AsyncTask<String, Void, Void> {
Socket socket;
PrintWriter pw;
#Override
protected Void doInBackground(String... voids) {
String mensaje_enviar = voids[0];
try {
socket = new Socket("192.168.1.8",1371);
pw = new PrintWriter(socket.getOutputStream());
pw.write(mensaje_enviar);
pw.flush();
pw.close();
socket.close();
}catch (IOException e){
e.printStackTrace();
}
return null;
}
}
CODE MAIN ACTIVITY (CLIENT ANDROID)
package com.example.app_test_client;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity{
EditText mensaje_enviar;
TextView mensaje_recibido;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mensaje_enviar = (EditText)findViewById(R.id.txtTexto);
mensaje_recibido = (TextView)findViewById(R.id.lblMensaje);
}
public void enviar(View v){
MessageSender MensajeRemitente = new MessageSender();
MensajeRemitente.execute(mensaje_enviar.getText().toString());
}
}
The void "enviar" I have it in the "onClick" button. All this to send messages from the client (android) to the server (vb.net) works for me.
Based on this class "MessageSender", I made another equal to receive messages on the client (android) but it has not worked
If you are trying to receive the message in the Android device, then you are missing reading the message itself with String messageReceived = input.readLine();. Your code would look like this:
...
socket = new Socket("192.168.1.8",1371);
InputStreamReader streamReader = new InputStreamReader(socket.getInputStream());
input = new BufferedReader(streamReader);
String messageReceived = input.readLine();
...
You will have the message sent from the server in messageReceived.
EDIT
Without getting into much details, when you read the data sent from the server, you need to know when the data sent "ends", and the easiest way you have with your current implementation is to print a "line end" (a vbCrLf character in VB) when you send the message. Thus, in your Sub btnEnviar_Click you need to add a vbCrLf as follows:
tcpservercliente.Client.Send(decode.GetBytes(txtMensajeEnviar.Text & vbCrLf))
Additional notes
When data is being read from the server the socket needs to know when the data ends. There are several ways of achieving this, but the easiest way is in your case is to read "a line ending" with String messageReceived = br.readLine();. If the server doesn't send any "line end" (as in your current implementation), it will keep waiting for it and hence it appears that the programs hungs. That is what is happening in your case when you note that you cannot do anything else after reading the message - it is just waiting for something that will never come.
It is not necessary that you check input.ready() when reading from the server. This will only be true when the data has been completely sent from the server, and there is a great chance that the data is still being sent when it is invoked.
If you want to know better how TCP sockets works, this SO question has good examples that you can try.
I'm developing an app to exchange data between an Android phone and a pc. I've chosen xml-rpc as a way to communicate, and as a library i downloaded android-xmlrpc (https://code.google.com/p/android-xmlrpc/).
When I call remote procedures from my phone, I use the XMLRPCClient and it works almost fine.
But then I have to synchronize data from my server to the application, so I need to listen on a given port and wait for a xmlrpc request.
I tried the following code:
protected Void doInBackground(Void... params) {
try { ServerSocket socket = new ServerSocket(8888);
XMLRPCServer server = new XMLRPCServer();
while (true) {
Socket client = socket.accept();
MethodCall call = server.readMethodCall(client);
String name = call.getMethodName();
}
} catch (Exception e) { Log.v(LOG_TAG, "Server: Error", e); }
return null;
}
But it seems it never receives any procedure call. I mean, to debug it I'm trying to use my XMLRPCClient as follow:
XMLRPCClient client = new XMLRPCClient("http://127.0.0.1:8888/");
Object o = client.call("add",1,3);
Log.v(LOG_TAG, o.toString());
And I always get no response. It's stuck on readMethodCall and never reads that the method I requested is "add"... It's strange it gets stuck there. Can't figure the reason why it is stucked here. Do you have any idea ?
I am creating a client-server communication application and would like the client to be able to detect and connect to the server automatically, given that they are on the same network.
Previously, my code was working across a Linux and Windows machine. I would broadcast a simple message and it could be read. I could also see the message while watching network traffic with Wireshark.
The approach I am taking is to
Get the broadcast address(es) on the network on the server.
For a given duration, broadcast a message (soon to be the server IP)
On the client side, wait until a message is received.
I am quite new to networking, so any obvious errors may not be immediately obvious to me.
Server broadcast code:
public class Broadcaster {
/* ... */
public void pulse() throws InterruptedException, IOException, SocketException {
Long elapsed = new Date().getTime();
Long timeout = elapsed + this.duration;
DatagramPacket packet = new DatagramPacket(this.message.getBytes(), this.message.length());
HashSet<InetAddress> channels = Broadcaster.getBroadcastChannels();
while(elapsed <= timeout) {
for(InetAddress channel : channels) {
DatagramSocket socket = new DatagramSocket(this.port);
socket.setBroadcast(true);
socket.connect(channel, this.port);
socket.send(packet);
System.out.println("Broadcast sent to " + channel.getHostAddress() + " (" + socket.getPort() + "): " + this.message);
socket.close();
}
Thread.sleep(this.frequency);
elapsed = new Date().getTime();
}
}
private static HashSet<InetAddress> getBroadcastChannels() throws SocketException {
/* Returns 192.168.0.255 */
}
public static void main(String[] args) {
Broadcaster heart = new Broadcaster("Hello from the Raspberry Pi!", 120000, 5000, 8027);
try {
heart.pulse();
} catch(SocketException e) {
/* ...etc... */
} finally {
System.out.println("Broadcasting completed.");
}
}
}
Client code:
public class BroadcastListener {
private int port;
private int length;
public BroadcastListener(int length, int port) {
this.port = port;
this.length = length;
}
public String getNext() throws IOException {
byte buffer[] = new byte[this.length];
DatagramSocket socket = new DatagramSocket(this.port);
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
System.out.println("Waiting on " + socket.getLocalSocketAddress());
socket.receive(packet);
socket.close();
return new String(buffer);
}
public static void main(String[] args) {
System.out.println("Listening for network broadcasts...");
BroadcastListener broadcast = new BroadcastListener(128, 8027);
try {
System.out.println("Received broadcast: " + broadcast.getNext());
} catch(IOException e) {
System.out.println("Could not receive broadcasts:");
System.out.println(e.getMessage());
}
}
}
The broadcast/netmask address as seen on both devices ifconfig output is netmask 255.255.255.0 broadcast 192.168.0.255
What confuses me the most is that Wireshark is still seeing the broadcast but when I run the client Java program, it just sits at socket.receive(packet);
Wireshark screenshot on Imgur
Both client & server are on port 8027. It is clear that the broadcaster is working, but the client broadcast listener is not. Does anyone have any idea what could be happening? Thanks!
As mentioned in the comments: Check your firewall :-)
Another thing i recognized was that if I sniff with wireshark, no other processes could receive that datagrams. After realizing that, I wrote a nodejs script, which exclusive=false by default but even that did not help. Maybe there is a kernel flag or something, that UDP datagrams cannot be 'consumed' by one process.
It looks like your server may be brodcasting on a different address than your client. Your client is not being assigned an InetAddress, try using this constructor for your socket in BroadcastListener
DatagramSocket socket = new DatagramSocket(new InetSocketAddress("192.168.0.255", this.port));
If that doesnt work you might try binding both your server and client to 127.0.0.1
You keep creating and destroying DatagramSockets. If the packet arrives at your host at a moment when you don't have a DatagramSocket bound to the port, it will be thrown away.
Create one DatagramSocket and leave it open for this life of this code.
Following is a thread which has a SOCKET listening at port 15445.
Whenever a Datagram packet is sent to it, it forwards back to the sender's address after adding a String(Reply from SERVER) in it. I want this code to run somewhere on the Internet, but I don't know where to start.
Is it possible? Can I run this code on a Tomcat server or do I need to do something different?
import java.io.*;
import java.net.*;
public class HelloWorld extends Thread {
protected DatagramSocket socket = null;
protected BufferedReader in = null;
public HelloWorld() throws IOException {
socket = new DatagramSocket(15445);
}
public void run() {
while (true) {
try {
byte[] buf = new byte[256];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
InetAddress address = packet.getAddress();
int port = packet.getPort();
String s = "Reply from SERVER";
byte[] b= s.getBytes();
packet = new DatagramPacket(b, b.length, address, port);
socket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException {
new HelloWorld().start();
}
}
No, Tomcat isn't a web server. It's a servlet/JSP engine that happens to have an HTTP server built in.
This looks like POJO with a main. Why can't you just run that as a service? Why do you think you need a web server?
Use Jetty (echo server is one of the tutorials afaik) and expose your port to the internet.
If your code works fine forward the necessary port through your router so it's reachable from the internet. If your looking for a hosted solution, vservers are a cheap way to start. http://www.superuser.com is the place to go for network configuration.
I am working on a server/client communication program and I am stuck at a problem. When I try to send messages from my client side it won't work properly. After initializing the server, I connect the client and that is successful. When I try to send messages from the client, the server won't receive them. After I close the client connection, the server receives all of the messages I attempted to send earlier. The following class is what I am using:
public class ServerSender extends Thread
{
private DataOutputStream out = new DataOutputStream(socket.getOutputStream());
private Scanner kb = new Scanner(System.in);
public void run()
{
while(true)
{
try
{
out.writeUTF(kb.nextLine());
out.flush();
} catch(IOException e) { System.out.println("error"); }
}
}
}
Any help would be much appreciated, thanks.
DataOutputStream doesn't have a buffer to flush, so your diagnosis is incorrect. However you need to be aware that writeUTF() writes a format that only DataInputStream.readUTF() can read. If you're trying to write lines you have the wrong API: try BufferedWriter.write()/.newLine().