I am learning about DatagramChannel Multicast,
I am trying to do the following ,i noticed that the DatagramChannel#receive method blocks completely when i am on VPN and does not receive anything , but data gets printed few iterations when i disconnect VPN.
1. Sending data to a multicast IP group:
import java.io.IOException;
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.util.Date;
public class MultiCastChannelThread extends Thread {
DatagramChannel channel;
ProtocolFamily family = StandardProtocolFamily.INET;
MultiCastChannelThread(String name) throws IOException {
super(name);
configureChannel();
}
public static void main(String[] args) throws IOException {
new MultiCastChannelThread("MultiCastChannel").start();
}
private void configureChannel() throws IOException {
channel = DatagramChannel.open(family).setOption(StandardSocketOptions.SO_REUSEADDR, true).bind(null).setOption(
StandardSocketOptions.IP_MULTICAST_IF, NetworkInterface.getByName("wlan0"));
}
#Override
public void run() {
int i = 0;
while (i++ < 6) {
try {
byte[] buff = new Date().toString().getBytes();
ByteBuffer buffer = ByteBuffer.wrap(buff);
InetAddress group = InetAddress.getByName("224.0.15.15");
int sent = channel.send(buffer, new InetSocketAddress(group, 4466));
System.out.format("Number of bytes sent :%s\n Data sent:%s\t\n", sent, new String(buff));
try {
sleep(5 * 1000);
} catch (InterruptedException e) {
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2. Joining and receiving the data on the group
import static java.lang.Thread.sleep;
import java.io.IOException;
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
public class MulticastChannelClient {
NetworkInterface networkInterface;
InetAddress inetAddress;
InetAddress group;
ProtocolFamily family = StandardProtocolFamily.INET;
public MulticastChannelClient() throws UnknownHostException, SocketException {
group = InetAddress.getByName("224.0.15.15");
networkInterface = NetworkInterface.getByName("wlan0");
}
public static void main(String[] args) throws IOException {
new MulticastChannelClient().testMultiCastChannel();
}
private void testMultiCastChannel() throws IOException {
new MultiCastChannelThread("MulticastChannelTest").start();
DatagramChannel channel = DatagramChannel.open(family).setOption(StandardSocketOptions.SO_REUSEADDR, true).bind(
new InetSocketAddress((InetAddress) null, 4466));
channel.join(group, networkInterface);
for (int i = 0; i < 6; i++) {
ByteBuffer received = ByteBuffer.allocate(250);
SocketAddress socketAddress = channel.receive(received);
System.out.println("Received ::: " + i + " " + new String(received.array()));
try {
sleep(2 * 1000);
} catch (InterruptedException e) {
}
}
}
}
Related
When I'm running a Java WebSocketStompClient, I got below error:
org.eclipse.jetty.websocket.api.MessageTooLargeException: Text message size [73728] exceeds maximum size [65536]
Sample code:
import org.apache.log4j.Logger;
import org.springframework.messaging.simp.stomp.StompFrameHandler;
import org.springframework.messaging.simp.stomp.StompHeaders;
import org.springframework.messaging.simp.stomp.StompSession;
import org.springframework.messaging.simp.stomp.StompSessionHandlerAdapter;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.web.socket.WebSocketHttpHeaders;
import org.springframework.web.socket.client.WebSocketClient;
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
import org.springframework.web.socket.messaging.WebSocketStompClient;
import org.springframework.web.socket.sockjs.client.SockJsClient;
import org.springframework.web.socket.sockjs.client.Transport;
import org.springframework.web.socket.sockjs.client.WebSocketTransport;
import org.springframework.web.socket.sockjs.frame.Jackson2SockJsMessageCodec;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutionException;
public class HelloClient {
private static Logger logger = Logger.getLogger(HelloClient.class);
StompSession session;
private final static WebSocketHttpHeaders headers = new WebSocketHttpHeaders();
public ListenableFuture<StompSession> connect() {
Transport webSocketTransport = new WebSocketTransport(new StandardWebSocketClient());
List<Transport> transports = Collections.singletonList(webSocketTransport);
SockJsClient sockJsClient = new SockJsClient(transports);
sockJsClient.setMessageCodec(new Jackson2SockJsMessageCodec());
WebSocketStompClient stompClient = new WebSocketStompClient(sockJsClient);
long[] hb = stompClient.getDefaultHeartbeat();
boolean en = stompClient.isDefaultHeartbeatEnabled();
long timeout = stompClient.getReceiptTimeLimit();
String url = "https://www.test.com";
return stompClient.connect(url, headers, new MyHandler());
}
public void subscribeMsg(StompSession stompSession) throws ExecutionException, InterruptedException {
stompSession.subscribe("/topic/test", new StompFrameHandler() {
public Type getPayloadType(StompHeaders stompHeaders) {
return byte[].class;
}
public void handleFrame(StompHeaders stompHeaders, Object o) {
logger.info("Received message " + new String((byte[]) o));
String response = new String((byte[]) o);
}
});
}
private class MyHandler extends StompSessionHandlerAdapter {
public void afterConnected(StompSession stompSession, StompHeaders stompHeaders) {
logger.info("Now connected");
session = stompSession;
}
}
public boolean isConnected() {
try {
Thread.sleep(500);
return session != null && session.isConnected();
} catch (Exception e) {
logger.warn("Error happens when checking connection status, ", e);
return false;
}
}
public static void main(String[] args) throws Exception {
HelloClient helloClient = new HelloClient();
ListenableFuture<StompSession> f = helloClient.connect();
StompSession stompSession = f.get();
helloClient.subscribeMsg(stompSession);
while (true) {
if (!helloClient.isConnected()) {
logger.info("wss diconnected ");
logger.info("need re-create ");
}
}
}
}
How to increase the limitation for a Java stomp websocket client? I found some not related answers How can I set max buffer size for web socket client(Jetty) in Java which are not suitable for stomp websocket client.
Also tried stompClient.setInboundMessageSizeLimit(Integer.MAX_VALUE); which doesn't work.
I want to create large number client connection to the server for the test purpose. I accomplish this by creating thread per connection, so I can only create 3000 connection on my machine. below is my code:
package com.stepnetwork.iot.apsclient.application;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
/**
* Created by sam on 3/22/16.
*/
public class DtuClient extends Thread {
private static final String HOST = "192.168.54.36";
private static final int PORT = 30080;
private EventLoopGroup workerGroup;
private String dtuCode;
public DtuClient(String dtuCode, EventLoopGroup workerGroup) {
this.dtuCode = dtuCode;
this.workerGroup = workerGroup;
}
public void run() {
Bootstrap bootstrap = new Bootstrap(); // (1)
try {
bootstrap.group(workerGroup); // (2)
bootstrap.channel(NioSocketChannel.class); // (3)
bootstrap.option(ChannelOption.SO_KEEPALIVE, true); // (4)
bootstrap.handler(new ChannelInitializer<SocketChannel>() {
#Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new MyClientHandler());
}
});
ChannelFuture feature = bootstrap.connect(HOST, PORT).sync();
feature.addListener((future) -> {
System.out.println(dtuCode + " connected to server");
Channel channel = feature.channel();
ByteBuf buffer = Unpooled.buffer(256);
buffer.writeBytes(dtuCode.getBytes());
channel.writeAndFlush(buffer);
});
feature.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("completed");
}
}
Can I get more connection.
I had try another solution after doing google research, but the channel will close automatically.
here is my another solution
package com.stepnetwork.iot.apsclient.application;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import java.util.ArrayList;
import java.util.List;
/**
* Created by sam on 3/22/16.
*/
public class Test {
private static final String HOST = "192.168.54.36";
private static final int PORT = 30080;
public static void main(String[] args) throws InterruptedException {
EventLoopGroup workerGroup = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap(); // (1)
try {
bootstrap.group(workerGroup); // (2)
bootstrap.channel(NioSocketChannel.class); // (3)
bootstrap.option(ChannelOption.SO_KEEPALIVE, true); // (4)
bootstrap.handler(new ChannelInitializer<SocketChannel>() {
#Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new MyClientHandler());
}
});
List<Channel> channels = new ArrayList<>();
// create many connection here, but the channel will be closed atomically
for (int i = 0; i < 10000; i++) {
channels.add(bootstrap.connect(HOST, PORT).sync().channel());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
while (true) {
Thread.sleep(Integer.MAX_VALUE);
}
}
}
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
public class Client {
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket();
socket.connect(new InetSocketAddress(5000));
byte[] message = "Oh Hai!".getBytes();
DatagramPacket packet = new DatagramPacket(message, message.length);
socket.send(packet);
}
}
I have this code as a string and I need to get its methods statements loops for separate arrays
Can any body suggest a solution
You can use the StreamTokenizer to analyze a stream (e.g. StringReader).
Here you are an example:
import java.io.IOException;
import java.io.StreamTokenizer;
import java.io.StringReader;
public class Test {
public static void main(String[] args){
StreamTokenizer tokenizer = new StreamTokenizer(new StringReader("public static void main(String[] args){"));
tokenizer.parseNumbers();
tokenizer.wordChars('_', '_');
tokenizer.eolIsSignificant(true);
tokenizer.ordinaryChars(0, ' ');
tokenizer.slashSlashComments(true);
tokenizer.slashStarComments(true);
int token;
try {
while( (token = tokenizer.nextToken()) != StreamTokenizer.TT_EOF) {
if(token == StreamTokenizer.TT_WORD) {
System.out.println(tokenizer.sval);
}
}
} catch (IOException e) {
e.printStackTrace();
// Please handle this exception
}
}
}
This generates the following output:
public
static
void
main
String
args
Please have a look at this for further details:
https://docs.oracle.com/javase/7/docs/api/java/io/StreamTokenizer.html
I have been trying to get UDP multicast working with Netty 4.0.26 and 5.0.0.Alpha2, without any success. I have adapted some code from this post which in its edited form supposedly works, but does not for me. The attached code simply echoes "Send 1", "Send 2" etc. but the corresponding packets are never received.
In the expression localSocketAddr = new InetSocketAddress(localAddr, MCAST_PORT) I have tried port 0 as well, also without success. All kinds of other combinations of bind port and local address have been tried also.
The various socket options are copied from the other post I mentioned.
Can anyone tell me what I'm doing wrong? This is with Java 8 on WIndows 8.1.
Thanks very much,
Sean
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFactory;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOption;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramChannel;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.InternetProtocolFamily;
import io.netty.channel.socket.nio.NioDatagramChannel;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
public class MCast {
private static final String LOCAL_ADDR = "192.168.0.18";
private static final String MCAST_GROUP = "239.254.42.96";
private static final int MCAST_PORT = 9796;
public static void main(String[] args) throws Exception {
Thread sender = new Thread(new Sender());
Thread receiver = new Thread(new Receiver());
receiver.start();
sender.start();
sender.join();
receiver.join();
}
private static class MCastSupport {
protected InetAddress localAddr;
protected InetAddress remoteAddr;
protected InetSocketAddress localSocketAddr;
protected InetSocketAddress remoteSocketAddr;
protected DatagramChannel chan;
protected Bootstrap bootstrap;
public MCastSupport() {
try {
localAddr = InetAddress.getByName(LOCAL_ADDR);
remoteAddr = InetAddress.getByName(MCAST_GROUP);
localSocketAddr = new InetSocketAddress(localAddr, MCAST_PORT);
remoteSocketAddr = new InetSocketAddress(remoteAddr, MCAST_PORT);
NetworkInterface nif = NetworkInterface.getByInetAddress(localAddr);
bootstrap = new Bootstrap()
.group(new NioEventLoopGroup())
.handler(new SimpleChannelInboundHandler<DatagramPacket>() {
#Override
protected void messageReceived(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
System.out.println("Received: " + msg.content().getInt(0));
}
})
.channelFactory(new ChannelFactory<NioDatagramChannel>() {
#Override
public NioDatagramChannel newChannel() {
return new NioDatagramChannel(InternetProtocolFamily.IPv4);
}
})
.handler(new SimpleChannelInboundHandler<DatagramPacket>() {
#Override
protected void messageReceived(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
System.out.println("Received: " + msg.content().getInt(0));
}
})
.option(ChannelOption.SO_BROADCAST, true)
.option(ChannelOption.SO_REUSEADDR, true)
.option(ChannelOption.IP_MULTICAST_LOOP_DISABLED, false)
.option(ChannelOption.SO_RCVBUF, 2048)
.option(ChannelOption.IP_MULTICAST_TTL, 255)
.option(ChannelOption.IP_MULTICAST_IF, nif);
chan = (DatagramChannel) bootstrap.bind(localSocketAddr).sync().channel();
chan.joinGroup(remoteSocketAddr, nif).sync();
} catch (Throwable t) {
System.err.println(t);
t.printStackTrace(System.err);
}
}
}
private static class Sender extends MCastSupport implements Runnable {
#Override
public void run() {
try {
for (int seq = 1; seq <= 5; ++ seq) {
ByteBuf buf = Unpooled.copyInt(seq);
DatagramPacket dgram = new DatagramPacket(buf, remoteSocketAddr, localSocketAddr);
chan.writeAndFlush(dgram);
System.out.println("Send: " + seq);
Thread.sleep(5000);
}
} catch (Throwable t) {
System.err.println(t);
t.printStackTrace(System.err);
}
}
}
private static class Receiver extends MCastSupport implements Runnable {
#Override
public void run() {
try {
Thread.sleep(5 * 5000);
} catch (Throwable t) {
System.err.println(t);
t.printStackTrace(System.err);
}
}
}
}
The root of my issue was setting ChannelOption.IP_MULTICAST_LOOP_DISABLED to false. Leaving out that line (i.e. allowing IP_MULTICAST_LOOP_DISABLED to default to true) allows multicast to work as expected. Frankly, this doesn't make a lot of sense to me, but I have no more time to investigate.
I want to create a server that can accept multiple connections and then bind 2 clients as a pair and forward the data between these 2 clients. But it is about multiple pairs of clients. I already have multithread server that can create a new thread for each new connected client. The problem for me is that these threads dont know of each other and somehow I have to connect 2 clients to a connection pair.
For now I just create these pair connection as this: I wait for the first client, then I wait for the second client and then open a thread for the input of client 1 that gets forwarded to client 2 and the other way around. This is not usable for multiple clients.
How can I do this decent?
The way I see it, a client would need to
establish a TCP(?) connection with your server,
identify itself
give the ID of the other client it wishes to talk to
The first that connects would have to be kept on hold (in some global table in your server) until the second client connects.
Once a pair of clients would have been recognized as interlocutors, you would create a pair of threads to forward the data sent by each client to the other one.
UPDATE: Example
ClientSocket.java
package matchmaker;
import java.io.Closeable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class ClientSocket implements Closeable {
private final Socket socket;
private final InputStream in;
private final OutputStream out;
private final String ownId;
private final String peerId;
public ClientSocket(Socket socket) throws IOException {
this.socket = socket;
this.in = socket.getInputStream();
this.out = socket.getOutputStream();
DataInputStream din = new DataInputStream(in);
this.ownId = din.readUTF();
this.peerId = din.readUTF();
}
public ClientSocket(String server, int port, String ownId, String peerId)
throws IOException {
this.socket = new Socket(server, port);
this.socket.setTcpNoDelay(true);
this.in = socket.getInputStream();
this.out = socket.getOutputStream();
this.ownId = ownId;
this.peerId = peerId;
DataOutputStream dout = new DataOutputStream(out);
dout.writeUTF(ownId);
dout.writeUTF(peerId);
}
public String getOwnId() {
return ownId;
}
public String getPeerId() {
return peerId;
}
public InputStream getInputStream() {
return in;
}
public OutputStream getOutputStream() {
return out;
}
#Override
public void close() throws IOException {
socket.close();
}
}
Matchmaker.java: the server
package matchmaker;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Matchmaker extends Thread {
private static final Logger LOG
= Logger.getLogger(Matchmaker.class.getName());
private final int port;
private final Map<ClientPair,ClientSocket> waiting = new HashMap<>();
public static void main(String[] args) {
try {
int port = 1234;
int st = 0;
for (String arg: args) {
switch (st) {
case 0:
switch (arg) {
case "-p":
st = 1;
break;
default:
System.out.println("Unknown option: " + arg);
return;
}
break;
case 1:
port = Integer.parseInt(arg);
st = 0;
break;
}
}
Matchmaker server = new Matchmaker(port);
server.start();
server.join();
} catch (InterruptedException ex) {
LOG.log(Level.SEVERE, null, ex);
}
}
private Matchmaker(int port) {
this.port = port;
setDaemon(true);
}
#Override
public void run() {
try {
ServerSocket server = new ServerSocket(port);
while (true) {
ClientSocket socket = new ClientSocket(server.accept());
ClientPair pair = new ClientPair(
socket.getOwnId(), socket.getPeerId());
ClientSocket other;
synchronized(this) {
other = waiting.remove(pair.opposite());
if (other == null) {
waiting.put(pair, socket);
}
}
if (other != null) {
LOG.log(Level.INFO, "Establishing connection for {0}",
pair);
establishConnection(socket, other);
} else {
LOG.log(Level.INFO, "Waiting for counterpart {0}", pair);
}
}
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
}
}
private void establishConnection(ClientSocket socket, ClientSocket other)
throws IOException {
Thread thread = new StreamCopier(
socket.getInputStream(), other.getOutputStream());
thread.start();
thread = new StreamCopier(
other.getInputStream(), socket.getOutputStream());
thread.start();
}
}
StreamCopier.java: a thread that reads from an InputStream and writes to an OutputStream
package matchmaker;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
public class StreamCopier extends Thread {
private static final Logger LOG
= Logger.getLogger(StreamCopier.class.getName());
private final InputStream in;
private final OutputStream out;
public StreamCopier(InputStream in, OutputStream out) {
this.in = in;
this.out = out;
setDaemon(true);
}
#Override
public void run() {
LOG.info("Start stream copier");
try {
for (int b = in.read(); b != -1; b = in.read()) {
out.write(b);
}
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
} finally {
LOG.info("End stream copier");
try {
out.close();
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
}
}
}
}
ClientPair.java: a pair of client IDs
package matchmaker;
public class ClientPair {
private final String client1;
private final String client2;
public ClientPair(String client1, String client2) {
this.client1 = client1;
this.client2 = client2;
}
public String getClient1() {
return client1;
}
public String getClient2() {
return client2;
}
public ClientPair opposite() {
return new ClientPair(client2, client1);
}
#Override
public int hashCode() {
int hash = 5;
hash = 73 * hash + client1.hashCode();
hash = 73 * hash + client2.hashCode();
return hash;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final ClientPair other = (ClientPair) obj;
return client1.equals(other.client1) && client2.equals(other.client2);
}
#Override
public String toString() {
return "[" + client1 + "," + client2 + "]";
}
}
ReaderClient.java: a sample client that reads from the socket and writes to standard output
package matchmaker;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ReaderClient {
private static final Logger LOG = Logger.getLogger(ReaderClient.class.getName());
public static void main(String[] args) {
try (ClientSocket client
= new ClientSocket("localhost", 1234, "reader", "writer")) {
Reader reader
= new InputStreamReader(client.getInputStream(), "UTF-8");
BufferedReader in = new BufferedReader(reader);
for (String s = in.readLine(); s != null; s = in.readLine()) {
System.out.println(s);
}
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
}
}
}
WriterClient.java: a sample client that writes to the socket
package matchmaker;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.logging.Level;
import java.util.logging.Logger;
public class WriterClient {
private static final Logger LOG = Logger.getLogger(ReaderClient.class.getName());
public static void main(String[] args) {
try (ClientSocket client
= new ClientSocket("localhost", 1234, "writer", "reader")) {
Writer writer
= new OutputStreamWriter(client.getOutputStream(), "UTF-8");
PrintWriter out = new PrintWriter(writer);
for (int i = 0; i < 30; ++i) {
out.println("Message line " + i);
}
out.flush();
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
}
}
}