set timeout for socket receive - java

I want to send data to server, then wait for an answer for one minute and then close the socket.
How to do it?
DatagramPacket sendpack = new ......;
socket.send(pack);
DatagramPacket recievepack = new .....;
//wait 1 minute{
socket.recieve(buf);
//wait 1 minute}
socket.close();

You can try this. Change the timeout of the socket as required in your scenario! This code will send a message and then wait to receive messages until the timeout is reached!
DatagramSocket s;
try {
s = new DatagramSocket();
byte[] buf = new byte[1000];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
InetAddress hostAddress = InetAddress.getByName("localhost");
String outString = "Say hi"; // message to send
buf = outString.getBytes();
DatagramPacket out = new DatagramPacket(buf, buf.length, hostAddress, 9999);
s.send(out); // send to the server
s.setSoTimeout(1000); // set the timeout in millisecounds.
while(true){ // recieve data until timeout
try {
s.receive(dp);
String rcvd = "rcvd from " + dp.getAddress() + ", " + dp.getPort() + ": "+ new String(dp.getData(), 0, dp.getLength());
System.out.println(rcvd);
}
catch (SocketTimeoutException e) {
// timeout exception.
System.out.println("Timeout reached!!! " + e);
s.close();
}
}
} catch (SocketException e1) {
// TODO Auto-generated catch block
//e1.printStackTrace();
System.out.println("Socket closed " + e1);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

If you are using DatagramSocket, or Socket you can use,
socket.setSoTimeout(1000);
//the value is in milliseconds
For any detail, you should've taken a look in DatagramSocket javadoc or Socket javadoc.

To clarify EJP's comment, this is what he meant by a "missing break" causing a SocketException.
String group = "224.0.0.0";
int port = 5000;
MulticastSocket recvSock = new MulticastSocket(port);
recvSock.joinGroup(InetAddress.getByName(group));
recvSock.setSoTimeout(1000);
while(true) {
try {
recvSock.receive(in);
} catch (SocketTimeoutException e) {
break; // Closing here would cause a SocketException
}
}
// Move the close() outside the try catch bloock
recvSock.leaveGroup(InetAddress.getByName(group));
recvSock.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.

how to read multiple lines from client to server

So i'm trying to send multiple lines of code everytime i type something in the client console. However when doing this it only prints the output of the client in the server once, what i would like to do is print the clients output in the server everytime after entering a line.
Client:
try {
Scanner scanner = new Scanner(System.in);
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
DataOutputStream outputStream;
System.out.println("Write something to client:");
while(scanner.hasNext()) {
System.out.println("Write something to client:");
outputStream = new DataOutputStream(socket.getOutputStream());
String message = scanner.nextLine();
outputStream.writeUTF(message);
}
} catch (IOException e) {
System.out.println("[ERROR] Unable to get streams from server");
}
}
ClientThread:
#Override
public void run() {
try {
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
System.out.println(inputStream.readUTF());
} catch (IOException e) {
e.printStackTrace();
}
}
Server:
public Server() {
try {
serverSocket = new ServerSocket(port);
System.out.println("[SERVER] Server initialized successfully");
// consider using!
Runtime.getRuntime().addShutdownHook(new Thread());
} catch (IOException e) {
System.out.println("[ERROR] Unable to launch server on port " + port);
}
while (true) {
Socket socket = null;
try {
socket = serverSocket.accept();
} catch (IOException e) {
System.out.println("[ERROR] Unable to accept client request");
}
System.out.println("[SERVER] New user joined the chat: " + socket);
groupCounter++;
ClientThread client = new ClientThread("Client " + groupCounter, socket);
Thread thread = new Thread(client);
thread.start();
groupClients.add(client);
//System.out.println(groupCounter);
}
The problem is in the server side, serverSocket.accept() stops the execution and waits for a client to connect to the server socket. That's why you only receive one message every time.
Add an infinite loop in the ClientThread to make sure it keeps on reading the client socket input.
try {
while (true) {
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
System.out.println(inputStream.readUTF());
}
} catch (IOException e) {
e.printStackTrace();
}

How to send message to multiple clients in a list from server

I had tried the following code as server to send message to the clients whose ip is in List mSession
for (MSession mSession : mSessions)
{
System.out.println("Inside for each");
System.out.println("IP TEST : " + mSession.getRemote_Addr());
ServerSocket srvr = new ServerSocket(1324, 5, InetAddress.getByName(mSession.getRemote_Addr()));
Socket skt = srvr.accept();
System.out.println("IP1:" + InetAddress.getByName(mSession.getRemote_Host()));
System.out.println("IP2:" + skt.getInetAddress().getHostAddress());
System.out.print("Server has connected!\n");
PrintWriter out = new PrintWriter(skt.getOutputStream(), true);
System.out.print("Sending string: '" + data + "'\n");
out.print(data);
out.close();
skt.close();
srvr.close();
}
The client side code:
InetAddress ip = InetAddress.getByName(host[0]);
System.out.println("IP SERVER : " + ip);
Socket skt = new Socket(ip, 1324);// Ip address of server
in = new BufferedReader(new InputStreamReader(skt.getInputStream()));
System.out.print("Received string: ");
while (!in.ready()) {}
data = in.readLine();
System.out.println(in.readLine());
System.out.print("'\n");
Popupapp app = new Popupapp();
app.fdis(data);
in.close();
skt.close();
I am getting bindexception cannot assign requested address : JVM_Bind
I have tried other ports but the exception remains the same
I had tried ports 8080, 8089,8086,8009,1234,8242,8006
Please help me to fix this.
I had tried on this simple program and it is showing same exception
public class ServerSide extends Thread{
public void run()
{
while(true)
{
String data = "Recieved new notification";
try {
ServerSocket srvr = new ServerSocket(1234, 5, InetAddress.getByName("192.168.168.40"));
Socket skt = srvr.accept();
skt.getInputStream();
System.out.print("Server has connected!\n");
PrintWriter out = new PrintWriter(skt.getOutputStream(), true);
System.out.print("Sending string: '" + data + "'\n");
out.print(data);
out.close();
skt.close();
srvr.close();
Thread.sleep(500);
}
catch(Exception e) {
System.out.print("Whoops! It didn't work!\n" + e);
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
The reason is that you're creating server socket inside the foreach loop. So, after the first time, when the first client is processed and the serversocket is created for the first time, this code again tries to create another serversocket on the same port in the next client processing, thereby resulting in the bind-exception.
The solution is to create a separate serversocket before the loop, which would keep on accepting clients inside the foreach loop. It is shown below :
ServerSocket srvr = new ServerSocket(1324, 5, InetAddress.getByName(mSession.getRemote_Addr()));
for (MSession mSession : mSessions)
{
System.out.println("Inside for each");
System.out.println("IP TEST : " + mSession.getRemote_Addr());
// start accepting client-requests
Socket skt = srvr.accept();
System.out.println("IP1:" + InetAddress.getByName(mSession.getRemote_Host()));
System.out.println("IP2:" + skt.getInetAddress().getHostAddress());
System.out.print("Server has connected!\n");
PrintWriter out = new PrintWriter(skt.getOutputStream(), true);
System.out.print("Sending string: '" + data + "'\n");
out.print(data);
out.close();
skt.close();
}
// finally close the server-socket!
srvr.close();
Based on your EDIT :
You're again creating your ServerSocket inside the loop! DON'T!!!* Do it in the constructor(or in some another method).
public class ServerSide extends Thread{
public ServerSide(){
ServerSocket srvr = new ServerSocket(1234, 5, InetAddress.getByName("192.168.168.40"));
}
public void run()
{
while(true)
{
String data = "Recieved new notification";
try {
Socket skt = srvr.accept();
skt.getInputStream();
System.out.print("Server has connected!\n");
PrintWriter out = new PrintWriter(skt.getOutputStream(), true);
System.out.print("Sending string: '" + data + "'\n");
out.print(data);
out.close();
skt.close();
srvr.close();
Thread.sleep(500);
}
catch(Exception e) {
System.out.print("Whoops! It didn't work!\n" + e);
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
Now, call it from your main-method on the server-side like :
new ServerSide().start();

Receive UDP packets in Async Task BackGround Process

protected String doInBackground(String... f_url) {
int count;
byte [] ip_bytes = new byte[] {(byte)192,(byte)168,(byte)1,(byte)100};
try {
InetAddress address = InetAddress.getByAddress(ip_bytes );
byte buffer[] = new byte[2000];
DatagramPacket p = new DatagramPacket(buffer, buffer.length, address, port);
try {
DatagramSocket ds = new DatagramSocket(port);
Log.d("..........","Perfect Binding .... Waiting for Data");
ds.receive(p);
publishProgress(""+p);
Thread.sleep(100);
Log.d("","Received :) ");
} catch(Exception e)
{
e.printStackTrace();
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
....................................
This is code for receiving UDP packet in Async Backgroung Process, But am not getting a single packet ... what is wrong in my code ?? How i can overcome this problem ?
It seems for receiving, you don't need to specify the ip and port in DatagramPacket.
DatagramPacket p = new DatagramPacket(buffer, buffer.length);

Can't receive String from UDP multicast

I'm having some problems receiving a String from a multicast.
It's the first time i'm using UDP multicast in Java.
I'm making a multiclient application over a LAN.
So i'm using Local Ip addresses.
I need the clients to find the server's IP address so they can send their data, requests, etc.
I let the server sent out a multicast with his own IP as a string every 5 seconds.
The clients should be able to receive it.
The problem is that they don't receive anything.
I'm testing with 2 devices so i don't need to use localhost.
Here's some of my code:
Server side:
public class MulticastIpSender extends Thread{
private String serverIp;
private int port;
private String multicastAddress;
private long WAITING_TIME = 5000; // 5 seconden
private DatagramSocket socket;
public MulticastIpSender(String serverIp, int port, String multicastAddress) throws SocketException {
super();
this.serverIp = serverIp;
this.port = port;
this.multicastAddress = multicastAddress;
socket = new DatagramSocket(port);
}
public void run() {
while(true){
try {
byte[] buf = new byte[256];
buf = serverIp.getBytes();
InetAddress group = InetAddress.getByName(multicastAddress);
DatagramPacket packet = new DatagramPacket(buf, buf.length, group, port);
socket.send(packet);
System.out.println("sent IP("+serverIp+") to group("+group+") on port "+port);
sleep(WAITING_TIME);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
I put this method in the main class:
private void sendIpAddressToListeners() {
try {
multicastIpSender = new MulticastIpSender(serverIp,PORT,"230.0.0.1");
multicastIpSender.run();
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I get the serverIp like this:
String hostName = InetAddress.getLocalHost().getHostName();
InetAddress addrs[] = InetAddress.getAllByName(hostName);
if (!addr.isLoopbackAddress() && addr.isSiteLocalAddress()) {
myIp = addr.getHostAddress();
}
}
System.out.println ("\nIP = " + myIp);
return myIp;
on this device it gives me 192.168.1.2
CLIENT SIDE:
multicastSocket = new MulticastSocket(PORT);
InetAddress address = InetAddress.getByName(MULTICAST_ADDRESS);
multicastSocket.joinGroup(address);
DatagramPacket serverIpPacket;
byte[] buf = new byte[256];
serverIpPacket = new DatagramPacket(buf, buf.length);
while(receivedIp ==null){
multicastSocket.receive(serverIpPacket);
receivedIp = new String(serverIpPacket.getData(), 0, serverIpPacket.getLength());
System.out.println("received server ip: " + receivedIp);
}
!! PORT = 4445 in both server and client
I hope somebody can help me with this or can explain a better way to do this.
Send a normal DatagramPacket on broadcast address, the packet will be received by all hosts in local network (with same network configuration, important part is mask)
Use calculator to check your broadcast address, this one works good: http://www.subnet-calculator.com/

Categories