I'm working on a small project for learning purposes , consisting of two instances of clients and a server instance .
The server and one of the clients are running on my PC whose code is written in Java , while the 2nd client runs on android .
The server is listening on a given port. When the Java client sends a packet to the server , it retains the IP / port to send in response to a future packet received from the android terminal , and vice versa.
Communications between each client and server working properly. But when communicating between clients ( assuming each acquired the ip / port on the other , as a response from the server) nothing comes to android terminal.
In both instances of the client, the socket is created as :
DatagramSocket socket = new DatagramSocket ();
Then contact the server only once , to store my address data :
Socket.Send ( sendPacket ) ;
( SendPacket is instantiated with fixed data server)
And then instantiate the listen method , passing as parameter one datagram packet containing only the number of bytes to receive.
socket.receive (packet );
Implementing this method in an infinite loop , I've only managed to receive packets from the server ( the answers ) and not the other client application.
The permissions in the manifest I use are:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
I appreciate any tip . Thank you very much !
I have implemented two socket one for send and another for receiving and is working for me whit some modifications attending to my needs. I am assuming you are forgetting the port ... or something... put a log of your error or more code to help you...
Below is the code working for me
int port =1515;
DatagramSocket socket = null;
try {
socket = new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
try {
socket.setBroadcast(true);
} catch (SocketException e) {
e.printStackTrace();
}
//////send socket
int eport = 1616;
InetAddress eip = null;
try {
eip = InetAddress.getByName("192.168.1.1"); ////SERVER IP ADDRESS ---- Server comunication is working so I assume you have it
} catch (UnknownHostException e) {
e.printStackTrace();
}
DatagramSocket esocket = null;
try {
esocket = new DatagramSocket(eport);
} catch (SocketException e) {
e.printStackTrace();
}
//////Start receive
while(true)
{
byte[] message = new byte[60*1024];
DatagramPacket recv_packet = new DatagramPacket(message, message.length);
try {
socket.receive(recv_packet);
} catch (IOException e) {
e.printStackTrace();
}
///Do something whit recv_packet
}
Related
Intro
There are a number of tutorials on creating a multicast publisher and receiver.
I used the one found here with a few modifications.
A few others:
here
here
here
note that these tutorials are all quite similar.
Details:
The server runs on port 7777 and sends datagrams to 224.0.0.0 (I tested a couple of other ip's in the multicast range: 224.0.0.0 to 239.255.255.255, but these didn't work)
Client then joins the multicast group 224.0.0.0 and waits for a packet response (run as a thread)
extra: I send a message like: 123.23.13.12[host-name]:1234 as the datagram data.
Problem:
Multicast packets from server (on localhost) not reaching client (on localhost).
Clients include a java console application (code found below) and Android application on Android Emulator. Both clients do not receive multicast packets.
I know that the multicast packets are being sent as this is shown in Wireshark
Below you will find a basic example of that which I have.
TL;DR: Server sends multicast packets (confirmed via Wireshark) but client doesn't receive them.
Suggestions are very welcome!
UPDATE
Based on Just another Java programmer's comment, I check my firewall. Lo and behold, my firewall was dropping on the input and forward chains. I set this to acceptall incoming (temporarily)
Based on Ron Maupin's comments.
I have changed the message sent to exclude the hostname, thus the message sent is 123.12.13.23:1234
I have changed the multicast send address to 239.254.0.0 which is within the specified range (see Ron's comment)
the multicast port is set to 7777
the outgoing interface is set with s.setInterface(InetAddress.getLocalHost()) in the broadcastServer() try catch block
With these changes applied, the client(s) still do not receive any packets.
Code:
Server Side (Console App):
String multicastAddress = "239.254.0.0", multicastPort = 7777;
private void broadcastServer() {
String message = null;
MulticastSocket s = null;
InetAddress local = null, group = null;
InetAddress[] allByName;
try {
local = InetAddress.getLocalHost();
s = new MulticastSocket(multicastPort);
s.setReuseAddress(true);
s.setInterface(local)
s.joinGroup(InetAddress.getByName(multicastAddress));
group = InetAddress.getByName(multicastAddress);
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
MulticastSocket socket = s;
// getNetworkIP() gets lan network ip
// serverport = 1025
message = local.getHostAddress() + ":" + String.valueOf(serverPort);
byte[] buf = message.getBytes();
DatagramPacket packet = new DatagramPacket(buf, buf.length, group, multicastPort);
thdBroadcaster = new Thread(() -> {
while (bRunServer) {
try {
Thread.sleep(1000);
printf("[Broadcast] Broadcasting...");
socket.send(packet);
printf("OK\n");
printf("");
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
socket.close();
});
thdBroadcaster.start();
}
Client Side (Console app):
String multicastAddress = "239.254.0.0", multicastPort = 7777;
private void startServerListenerThread() {
Thread thdServerListener = new Thread(new Runnable() {
#Override
public void run() {
MulticastSocket socket = null;
InetAddress group = null;
try {
socket = new MulticastSocket(multicastPort);
socket.setReuseAddress(true);
group = InetAddress.getByName(multicastAddress);
socket.joinGroup(group);
handleServerBroadcasts(socket);
socket.leaveGroup(group);
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void handleServerBroadcasts(final MulticastSocket socket) {
while (true){
try {
byte[] buf = new byte[256];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
String received = new String(packet.getData());
String address = received.substring(0, received.indexOf(":"));
String port = received.substring(received.indexOf(":") + 1);
System.out.println();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception x){
x.printStackTrace();
}
}
}
});
thdServerListener.start();
}
You are calling setReuseAddress() after binding the socket. It has no effect. You need to create an unbound MulticastSocket, call setReuseAddress(), and then bind it.
The solution ended up being a trivial change.
Resolving the issue was as simple as changing:
s = new MulticastSocket(multicastPort);
to
s = new MulticastSocket();
on the server side ONLY
Note: The firewall is a requirement, check if multicast packets are allowed through. The interface I used is localhost, not a requirement though. However this can be set by getting the specified interface you need.
UPDATE
EJP's comment:
I changed the port used to 8888. This port was used to send server datagrams and for the client to connect on with their MulticastSocket
I have problems using Sockets on Android. I'm new to this topic so I try to achieve a simple chat, Android phone to another Android phone as a training.
I can use my code to create a ServerSocket and connect to it with another Socket from the same device ( An 'echo' example with only one client on one device works fine) I've done that also using two IP adresses on the same wifi (192.168...) but any tentative to connect a distant client using internet ip address using 3G connection fails with a
java.net.SocketException: recvfrom failed: ETIMEDOUT (Connection timed out)
What I do is, creating the ServerSocket (ServerConnect.java) :
private ServerSocket _mainServer = null;
private void initServer() {
try {
//port I use here is arbitrary: 8081
_mainServer = new ServerSocket(CONNECT_SOCKET_PORT);
} catch (IOException e) {
Log.w("ServerSocket", e.toString());
e.printStackTrace();
}
}
in the same class, in a separate thread I do this to wait for client connections :
while (running) {
GuestConnect ssc = new GuestConnect(_mainServer.accept());
ssc.setListener(this);
ssc.startConnection();
_clientSockets.add(ssc);
performGuestAdded("bra!");
}
it makes the server waiting for multiple client connection, so it can host more than two poeple in the 'chat room'.
The comunication server side is made from the local client callback and dispatch messages to all my guests (I'm still working on this part, its not really done yet but I don't think its relevant to my problem here) :
public void onMessageReceived(TBTGuestConnect sender, String message) {
for(TBTGuestConnect guestConnect : _clientSockets)
if(guestConnect != sender)
guestConnect.sendMessage(message);
}
Clients are store as 'GuestConnect' objects here is how I set them (GuestConnect.java):
public class GuestConnect {
private StringBuilder _currentMessage;
private BufferedReader _is;
private PrintStream _os;
private Socket _clientSocket = null;
private String _hostname;
private boolean _running = false;
public GuestConnect(String hostname) {
_hostname = hostname;
_currentMessage = new StringBuilder();
}
clientSocket initialisation (still GuestConnect.java):
private void initSocket() {
if(_clientSocket==null)
{
// Try to open a server socket on given port
// Here is the fail when I called it from another device
try {
_clientSocket = new Socket(_hostname, ServerConnect.CONNECT_SOCKET_PORT);
} catch (IOException e) {
Log.w("GuestSocket", e.toString());
}
}
// Create a socket object from the ServerSocket to listen and accept
// connections.
// Open input and output streams
try {
_is = new BufferedReader(new InputStreamReader(_clientSocket.getInputStream()));
_os = new PrintStream(_clientSocket.getOutputStream());
} catch (IOException e) {
Log.w("GuestSocket", e.toString());
}
}
again, in the same class there is the comunication part :
initSocket();
_running = true;
performConnectionStarted();
try {
while (_running) {
String received = _is.readLine();
_currentMessage.append(received);
if (received.contains(ServerConnect.CONNECT_SOCKET_MESSAGE_END)) {
String finalMsg = _currentMessage.toString().substring(0, _currentMessage.lastIndexOf(ServerConnect.CONNECT_SOCKET_MESSAGE_END));
performMessageReceived(finalMsg);
_currentMessage.setLength(0);
}
}
} catch (IOException e) {
Log.w("GuestSocket", e.toString());
performError(e);
} finally {
try {
_os.close();
_is.close();
_clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
performError(e);
}
_clientSocket = null;
}
I can then send a message from this method :
public void sendMessage(String toSend) {
if (_running)
_os.println(toSend+ServerConnect.CONNECT_SOCKET_MESSAGE_END);
else
throw new IllegalStateException("Send message : Connection isn't started !");
}
So the question is, what should I do to make this works using global internet ip addresses ?
And more generally, what it the technical difference between same wifi local ip address and internet ip adress ?
i'll start from the end because it's easier - local ip address is private, it's not valid (and not visible) out of your local network, someone out of your local network can't access it directly but you can access hosts with public ip addresses. because they are not universally visible private addresses are not unique, public ip addresses are unique and (normally) visible from any point on the internet. there's more on the subject http://en.wikipedia.org/wiki/Network_address_translation
when it comes to 3g networks take a look here Could I connect to my iphone using 3g ip? and here ServerSocket accept() not accepting connections on Android . so most probably it can't be done
Don't know if this would be of any importance to you but in our country most 3G accounts are blocked by the ISP from incoming connections. You have to apply to unblock the ports. Some ISP's won't unblock them and some will.
Found that out when I wanted to connect my DVR with a 3G modem.
i want to program a server/client app in android.
i have one server class on my pc and client on my android phone.
all permissions are ok.
Here is client:
try {
mysocket = new Socket("My PC IP Address", 4444);
} catch (UnknownHostException e) {...
} catch (IOException e) {...
}
here is server:
try {
myServerSocket = new ServerSocket(4444);
} catch (IOException e) {...
}
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
System.out.println("Connection Established.");
} catch (IOException e) {
}
I uses "Connectify" program on my pc to have an (virtual)access point such that my phone connect to that.
But when I try to connect to server in my android app, it hangs and then throws Timed-out exception.
This code doesn't look bad.
Are you certain Connectify is working well?
You shoud try running both the server and the client you have built on your PC, using two different processes (as an example the server as a standalone and the client in the Android Emulator).
If it works properly from localhost to localhost:4444, the the connection is the cause of the problem, not your code. And otherwise, you will easily find the bug in your code.
I have an app in android in which I created an android client and a Java sever.
But I'm confronting the following issue: my client (the android part) connects to the local machine on port 6000 using the android loopback address.
My server (in Java) listens on local machine at the port 6000 - but what is the IP I have to use to get the socket that accepts the clients?
InetSocketAddress serverAddr = new InetSocketAddress(SERVERIP,serverPort);
serverSocket = new ServerSocket();
serverSocket.bind(serverAddr);
So what is the SERVERIP I have to use?
UPDATE:My client runns on an emulator!!!!!
EDIT:
public class ClientThread implements Runnable {
Object syncToken;
public ClientThread(Object syncToken) {
this.syncToken = syncToken;
}
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(serverIpAddress);
socket = new Socket(serverAddr, 50458);
} catch (UnknownHostException e) {
System.err.println("Don't know about host");
} catch (IOException e) {
System.err
.println("Couldn't get I/O for the connection to host");
}
try {
out = new PrintStream(socket.getOutputStream());
} catch (IOException e) {
System.out.println(e);
}
while (true) {
synchronized (syncToken) {
try {
syncToken.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
And here is: private String serverIpAddress = "10.0.2.2";!!!!!
From http://developer.android.com/guide/developing/devices/emulator.html#emulatornetworking: if you want to communicate from within the emulator to the local host, use IP 127.0.0.1 on the local host and use IP 10.0.2.2 in Android. This should let you communicate between the Android client and the local host server.
You want to run the server part on the Android? I guess not, and in such case using loopback address is not really going to work, as loopback interface on the Android system loops back to the Android machine itself, it is not routed to the outside.
For the serverAddr, use the #InetSocketAddress(int port) constructor, it specifies the wildcard address and a specific port, meaning it listens on all the interfaces of the machine.
Edit: For best results, on the android device use the DNS name of the server to connect to it.
Hay Guys, I'm new to Android but heres what i want to do.
I want to beable to open a connect to a server using a given IP and PORT, then send commands to the server and get data back.
Any ideas what i need to google to help on this? I know how to do it in PHP (using fputs, fgets, and fsockopen).
any help would be brill.
Thanks
Use the java.net classes. Below is a simple example using DatagramSockets:
String cmd("my command");
try {
InetSocketAddress address = new InetSocketAddress("10.1.1.1", 12350);
DatagramPacket request = new DatagramPacket(cmd.getBytes(), cmd.length(), address);
DatagramSocket socket = new DatagramSocket();
socket.send(request);
} catch (SocketException e) {
...
}
} catch (IOException e) {
...
}
}
Other Java samples can be found here: