I have to send UDP broadcast in Android.I am always getting java.io.IOException: Invalid argument at socket.send(packet).
When creating object of socket I sometimes get Address already in use Exception
My Code Complete code is (Edit 2) :
private void setBroadCastMessage() {
final int udpPortNumber = 6000;
ConnectivityManager connManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo mWifi = connManager.getActiveNetworkInfo();
if (mWifi.getType() == ConnectivityManager.TYPE_WIFI) {
if (mWifi.isConnected()) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
try {
InetAddress address;
address=InetAddress.getByName("255.255.255.255");
DatagramSocket datagramSocket = new DatagramSocket(udpPortNumber,address);
messageBroadCast(datagramSocket,address);
} catch (SocketException e) {
e.printStackTrace();
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
thread.start();
}
}
}
public void messageBroadCast(DatagramSocket socket, InetAddress address)
{
String data="This is my discovery request";
DatagramPacket packet = new DatagramPacket(data.getBytes(), data.length(),
address, 6000);
try {
socket.send(packet);
LogUtils.errorLog("Address :"," "+address);
LogUtils.errorLog("Send String:"," "+data);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Can't really post this as a comment but here is the code I have used which works and is extremely similar to yours.
Try this and add your stack trace to the question if you have further issues.
I use this to successfully broadcast to IP address "255.255.255.255"
private void sendToIP(String ip, int port, String message) {
try {
DatagramSocket socket = new DatagramSocket();
byte[] sendData = message.getBytes();
InetAddress IPAddress = InetAddress.getByName(ip);
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port);
socket.send(sendPacket);
} catch (Exception e) {
e.printStackTrace();
}
}
If you want to broadcast, you may need to call DatagramSocket.setBroadcast(true). But broadcast of the type you're attempting here has been deprecated for over 20 years.
Related
Is it possible to write a client-server code that can connect 2-different computers to play a multi-player game using sockets in java? Do these computers need to be connected by a cable? Or can I send the data through some other source? (Like internet..) Or is it enough if I know just the ip addresses of both computers and put that in in the sockets? Please tell me how I can do it.
You can connect computers that are on the same Wifi network. You will need to open a server and then open clients that connect to it.
The following code may help:
Server.java
ArrayList<Socket> clientSockets = new ArrayList<>();
try {
ServerSocket serverSocket = new ServerSocket(port); // port same as client
InetAddress inetAddress = InetAddress.getLocalHost();
System.out.println("Server opened at: "+inetAddress.getHostAddress());
while (true) // this keeps the server listening
{
final Socket socket = serverSocket.accept(); // this accepts incomming connections
clientSockets.add(socket); // adds current connection to an arraylist
System.out.println(timestamp()+"Connection from "+socket.getInetAddress());
Thread t = new Thread(new Runnable() // Thread handles messages sent by client that just connected
{
#Override
public void run() {
try
{
while (socket.isConnected())
{
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String fromClient = br.readLine();
if (fromClient != null)
{
//use message from client
}
else // connection might have been reset by client
{
socket.close();
clientSockets.remove(socket);
}
}
} catch (SocketException e)
{
System.out.println("Disconnection from "+socket.getInetAddress());
} catch (IOException e) {}
}
});
t.start();
}
} catch (Exception e) {}
Client.java - add two buttons, one for connecting and one for sending
bConnect.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
try {
InetAddress address = InetAddress.getByName(host); // host IPaddress
socket = new Socket(address, port); // port same as server
bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
final Timer time = new Timer(); // to get new server txt if it changes
TimerTask t = new TimerTask() {
#Override
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String kry = br.readLine();
// use message from server
} catch (Exception e1) {
JOptionPane.showMessageDialog(null, "The Server has just gone offline");
}
}
};
time.scheduleAtFixedRate(t, 0, 2000);
}
catch (Exception e1)
{e1.printStackTrace();
JOptionPane.showMessageDialog(null, "The Server is not online");}
}
});
bSend.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String textGekry = "what you are sending";
if (!textGekry.equals(""))
{
String sendMessage = textGekry + "\n";
try
{
bw.write(sendMessage);
bw.flush();
}
catch (Exception e1)
{
JOptionPane.showMessageDialog(null,"The Server is most likely offline");
}
}
}
});
I try to send and receive data between android and pc over UDP.
This is code in android:
String hostAddress = "10.0.2.2";
private static final int port = 2017;
DatagramSocket socket = null ;
InetAddress host;
String message = "hello";
#Override
public void run() {
try {
host = InetAddress.getByName(hostAddress);
socket = new DatagramSocket();
DatagramPacket packet = new DatagramPacket(message.getBytes(), message.length(), host, port);
socket.setBroadcast(true);
while(true){
socket.send(packet);
Thread.sleep(5000);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
and code in pc:
DatagramSocket socket;
public final int port = 2017;
public ArrivedMessages(){
try {
socket = new DatagramSocket(port);
System.out.println( "Ready!") ;
byte inFromClient[];
inFromClient = new byte[256];
DatagramPacket packet = new DatagramPacket(inFromClient, inFromClient.length);
while(true){
socket.receive(packet);
String data = new String(packet.getData());
System.out.println(packet.getData().toString());
}
} catch (SocketException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
but output in pc is not "hello" like message in android code. This is my output: [B#462d5aee
What should i do to fix it? Thanks!
String data = new String(packet.getData());
That should be:
String data = new String(packet.getData(), 0, packet.getLength());
and
System.out.println(packet.getData().toString());
should be:
System.out.println(data);
Otherwise you are just printing byte[].toString() of an incorrect-length byte array.
Learning java MulticastSocket, the same LAN only the machine can receive the broadcast, the other equipment can not. why? Is the router setting problem or the broadcast address setting problem?
send.java
public class sentServer {
public static void main(String[] args) {
String host = "224.0.0.1";
int port = 9998;String message = "test-multicastSocket";
try {
InetAddress group = InetAddress.getByName(host);
MulticastSocket s = new MulticastSocket();
s.joinGroup(group);
DatagramPacket dp = new DatagramPacket(message.getBytes(),message.length(),group,port);
s.send(dp);
s.close();
} catch (UnknownHostException e)
{
e.printStackTrace();
} catch (IOException e)
{e.printStackTrace();
}
}
}
The listening address set here is 224.0.0.1
recevier.java
public class reClinet {
public static void main(String[] args) {
String host="224.0.0.1";
int port=9998;
int length=1024;
byte[] buf=new byte[length];
MulticastSocket ms=null;
DatagramPacket dp=null;
StringBuffer sbuf=new StringBuffer();
try {
ms=new MulticastSocket(port);
dp=new DatagramPacket(buf,length);
InetAddress group=InetAddress.getByName(host);
ms.joinGroup(group);
System.out.println("port is open");
ms.receive(dp);
ms.close();
int i;
for(i=0;i<1024;i++){
if(buf[i]==0){
break;
}
sbuf.append((char)buf[i]);
}
System.out.println("message"+sbuf.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}
`
Thanks
In case you are asking: why can only systems attached to the same network segment see broadcasts?
That is the nature of broadcasts in Java: a client connects to a specific server; and joins the broadcast group; then that client will be notified.
If a client doesn't get those notifications; you have to look into your network settings, firewalls, ...
I'm trying to create a simple multicast communication between my PC (Ubuntu, client) and my phone (Android, server).
Unicast/TCP connections work without any problem, the defined port (37659) opens both on PC and phone. When trying to use a MulticastSocket, no ports get opened. nmap tells me the specified port (36963) is a TCP port and that it is closed. (While the receive-method is being executed).
Am I doing something wrong? Or is the firewall blocking the multicast sockets? (I've tried about 20 different ports and none worked..., currently using port 36963)
EDIT: Also with the firewall completely down, nmap tells me the port is closed...
The server's code (phone):
private void multicastLoop() {
String res = Build.FINGERPRINT + "\n";
final InetAddress group;
final MulticastSocket socket;
final DatagramPacket response;
try {
group = InetAddress.getByName("224.0.0.115");
socket = new MulticastSocket(mport);
socket.setLoopbackMode(true);
socket.setSoTimeout(10000);
socket.joinGroup(group);
response = new DatagramPacket(res.getBytes(), res.length(), group, mport);
} catch (IOException e) {
e.printStackTrace();
return;
}
Thread t = new Thread(new Runnable() {
#Override
public void run() {
while(isRunning) {
try {
byte[] data = new byte[1024];
DatagramPacket dm = new DatagramPacket(data, data.length);
socket.receive(dm);
Log.d("udp", "received");
if (Arrays.equals(dm.getData(), "someone there".getBytes())) {
socket.send(response);
}
} catch (SocketTimeoutException e) {
continue;
} catch (IOException e) {
e.printStackTrace();
}
}
try {
socket.leaveGroup(group);
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
t.start();
}
The client's code (computer):
public String[] findServers() {
String hello = "someone there";
try {
InetAddress group = InetAddress.getByName(mhost);
MulticastSocket socket = new MulticastSocket(mport);
socket.setLoopbackMode(true);
socket.setSoTimeout(60000);
socket.joinGroup(group);
DatagramPacket p = new DatagramPacket(hello.getBytes(), hello.length(), group, mport);
byte[] buffer = new byte[1024];
socket.send(p);
DatagramPacket r = new DatagramPacket(buffer, buffer.length);
socket.receive(r);
socket.leaveGroup(group);
socket.close();
String srinfo = "";
byte[] data = r.getData();
for (byte b: data)
srinfo += (char) b;
System.out.println("Server found at " + r.getAddress().getHostName() + ": " + srinfo);
} catch (SocketTimeoutException e) {
return new String[] {"timeout"};
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
Make sure mhost is set to "224.0.0.115" not some machine name.
Make sure multicast is enabled on your router.
If the host is multi-homed, you need to join the multicast group via all local interfaces, not just the default one, which is what you're doing at present.
You could send the response back to the source address it came from, which is in the received datagram packet. That would also mean that the client doesn't need a MulticastSocket, only a DatagramSocket.
Im trying to write server and client for service which would tell the current time. My code:
SERVER
public class TimeServer {
public static void main(String[] args) {
try {
final DatagramSocket so = new DatagramSocket(8189);
new Thread(new Runnable() {
#Override
public void run() {
try {
while (true) {
try {
InetAddress group = InetAddress.getByName("200.20.2.0");
byte[] buf = new byte[256];
Calendar cal = Calendar.getInstance();
buf = cal.toString().getBytes();
DatagramPacket packet = new DatagramPacket(buf, buf.length,
group, 8189);
so.send(packet);
} catch (IOException ex) {
ex.printStackTrace();
}
Thread.sleep((int)(Math.random() * 5));
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}).start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
CLIENT
public class TimeClient {
public static void main(String[] args) {
try {
MulticastSocket so = new MulticastSocket(8190);
InetAddress group = InetAddress.getByName("200.20.2.0");
so.joinGroup(group);
//5 razy czekamy na otrzymanie od serwera wiadomosci
for (int a=0; a<5; a++) {
byte[] buf = new byte[256];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
so.receive(packet);
String recv = new String(packet.getData());
System.out.println("RECEIVED: " + recv);
}
so.leaveGroup(group);
so.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
When launching server and then client I get the following error:
java.net.BindException: Address already in use
at java.net.PlainDatagramSocketImpl.bind0(Native Method)
at java.net.AbstractPlainDatagramSocketImpl.bind(AbstractPlainDatagramSocketImpl.java:95)
at java.net.DatagramSocket.bind(DatagramSocket.java:376)
at java.net.MulticastSocket.<init>(MulticastSocket.java:172)
at java.net.MulticastSocket.<init>(MulticastSocket.java:137)
at timeclient.TimeClient.main(TimeClient.java:13)
Please help, thanks
EDIT:
I changed client port and now I get exception:
java.net.SocketException: Not a multicast address
at java.net.MulticastSocket.joinGroup(MulticastSocket.java:306)
at timeclient.TimeClient.main(TimeClient.java:15)
What's now?
Every Port can only be used by a single application. In your case, your server and your client (2 applications) are trying to use the same port which is causing the exception.
To fix it, change for example the port for the client from 8189 to 8190
You must change the client port (or the server port) because every port only can be used by a single process.
try DatagramSocket.setReuseAddress(true) and see what happens.