How to implement SCTP protocol between a gateway and a server with java ?
If your target is Java 7 never try to implement it. As Andrew and Tom stated its already implemented as a core feature.
No need, just use sctp:
https://github.com/RestComm/sctp
Handles most needs, works great.
Windows cannot support SCTP. if want to does with windows plz install sctp driver.Other wise use linux am adding simple client server example
Client.java
package mai;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import com.sun.nio.sctp.MessageInfo;
import com.sun.nio.sctp.SctpChannel;
public class Client
{
public static void main(String[] args)
{
try {
//SocketAddress socketAddress = new InetSocketAddress( 6050);
InetSocketAddress socketAddress = new InetSocketAddress("192.9.200.193", 4444);
System.out.println("open connection for socket [" + socketAddress + "]");
SctpChannel sctpChannel = SctpChannel.open(socketAddress, 1,1); //(socketAddress, 1 ,1 );
sctpChannel.bind(new InetSocketAddress(4444)); //6060
sctpChannel.connect(socketAddress, 1 ,1);
System.out.println("sctpChannel.getRemoteAddresses() = " + sctpChannel.getRemoteAddresses());
System.out.println("sctpChannel.getAllLocalAddresses() = " + sctpChannel.getAllLocalAddresses());
System.out.println("sctpChannel.isConnectionPending() = " + sctpChannel.isConnectionPending());
System.out.println("sctpChannel.isOpen() = " + sctpChannel.isOpen());
System.out.println("sctpChannel.isRegistered() = " + sctpChannel.isRegistered());
System.out.println("sctpChannel.provider() = " + sctpChannel.provider());
System.out.println("sctpChannel.association() = " + sctpChannel.association());
System.out.println("send bytes");
final ByteBuffer byteBuffer = ByteBuffer.allocate(64000);
//Simple M3ua ASP_Up message
byte [] message = new byte []{1,0,3,1,0,0,0,24,0,17,0,8,0,0,0,1,0,4,0,8,84,101,115,116};
final MessageInfo messageInfo = MessageInfo.createOutgoing(null, 0);
System.out.println("messageInfo = " + messageInfo);
System.out.println("messageInfo.streamNumber() = " + messageInfo.streamNumber());
byteBuffer.put(message);
byteBuffer.flip();
sctpChannel.send(byteBuffer, messageInfo);
System.out.println("close connection");
sctpChannel.close();
System.in.read();
} catch (Exception e) {
e.printStackTrace();
try {
System.in.read();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
Server.java
package mai;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.util.Arrays;
import com.sun.nio.sctp.MessageInfo;
import com.sun.nio.sctp.SctpChannel;
import com.sun.nio.sctp.SctpServerChannel;
public class Server {
static ByteBuffer rxBuffer;
public static void main(String[] args)throws Exception {
rxBuffer = ByteBuffer.allocateDirect(64000);
rxBuffer.clear();
rxBuffer.rewind();
rxBuffer.flip();
// SctpChannel xx=SctpChannel.open();
com.sun.nio.sctp.SctpChannel sc = com.sun.nio.sctp.SctpChannel.open();
SocketAddress serverSocketAddress = new InetSocketAddress(4444);
System.out.println("create and bind for sctp address");
SctpServerChannel sctpServerChannel = SctpServerChannel.open().bind(serverSocketAddress);
System.out.println("address bind process finished successfully");
SctpChannel sctpChannel;
while ((sctpChannel = sctpServerChannel.accept()) != null) {
System.out.println("client connection received");
System.out.println("sctpChannel.getRemoteAddresses() = " + sctpChannel.getRemoteAddresses());
System.out.println("sctpChannel.association() = " + sctpChannel.association());
MessageInfo messageInfo = sctpChannel.receive(rxBuffer=ByteBuffer.allocateDirect(64000) , null, null);
int len= messageInfo.bytes();
System.out.println("Server... Total bytes recived "+len);
System.out.println("Server... "+messageInfo);
rxBuffer.flip();
byte[] data = new byte[len];
rxBuffer.get(data);
rxBuffer.clear();
System.out.println("Server..... data "+Arrays.toString(data));
System.out.println("Server..... close connection");
}
}
}
Related
I am using C# to create a client socket that should connect with a Java socket server. But no matter what I try the code always manages to send some sort of message, but for the Java server it's completely empty.
This is the C# client code:
using Godot;
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
public class Scanning: Control
{
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
string toSend = "Handshake:Interface";
IPEndPoint serverAddress = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 429);
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
clientSocket.Connect(serverAddress);
// Sending
int toSendLen = System.Text.Encoding.ASCII.GetByteCount(toSend);
byte[] toSendBytes = System.Text.Encoding.ASCII.GetBytes(toSend);
byte[] toSendLenBytes = System.BitConverter.GetBytes(toSendLen);
clientSocket.Send(toSendLenBytes);
clientSocket.Send(toSendBytes);
Console.WriteLine("Client received: " + rcv);*/
clientSocket.Close();
}
}
Java code that is responsible for working with the client:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
public class ClientHandler {
public PrintWriter out;
public BufferedReader in;
public Socket clientSocket;
public Thread thread;
public ClientHandler(Socket client) {
clientSocket = client;
System.out.println("Processing connection from " + clientSocket.getInetAddress());
thread = new Thread(new Runnable() {
#Override
public void run() {
try {
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), "UTF-8"));
ArrayList<String> cmdBuffer = new ArrayList<String>();
while (!Main.test.get()) {
String msg = in.readLine();
if(msg.startsWith("Handshake")) {
System.out.println("LOG: " + msg);
String[] work = msg.split(":");
if (!MessageChannel.clients.contains(work[1])) {
respond("1/I/Handshake successful for/" + work[1]);
respond("Connected: " + MessageChannel.clients);
MessageChannel.buffer.put(work[1], cmdBuffer);
MessageChannel.clients.add(work[1]);
}
} else if (msg.startsWith("Disconnect")) {
System.out.println("LOG: " + msg);
String[] work = msg.split(":");
MessageChannel.clients.remove(work[1]);
MessageChannel.buffer.remove(work[1]);
out.println("I/Disconnected/" + work[1]);
} else if(msg.startsWith("List")) {
System.out.println("LOG: " + msg);
respond("0/Connected: " + MessageChannel.clients);
} else {
String[] work = msg.split(":");
if (MessageChannel.clients.contains(work[0])){
if (work[1].equals("Lookup")) {
out.println(MessageChannel.buffer.get(work[0]).size() +"/Lookup:");
for (String e : MessageChannel.buffer.get(work[0])) {
out.println(e);
}
MessageChannel.buffer.replace(work[0], new ArrayList<String>());
} else {
System.out.println("LOG: " + msg);
MessageChannel.buffer.get(work[1]).add(work[2]);
respond("0/I/Success");
}
}
}
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
thread.start();
}
public void respond(String msg) {
out.println(msg);
System.out.println("LOGR: " + msg);
}
}
How can I fix that? Thanks in advance!
Please find below code, which runs fine on Windows 10 System and is able to discover remote devices across the network. On Linux we are creating a jar out of the code and running it using java -jar test.jar
package main;
import java.util.ArrayList;
import java.util.List;
import com.serotonin.bacnet4j.LocalDevice;
import com.serotonin.bacnet4j.RemoteDevice;
import com.serotonin.bacnet4j.RemoteObject;
import com.serotonin.bacnet4j.ServiceFuture;
import com.serotonin.bacnet4j.event.DeviceEventAdapter;
import com.serotonin.bacnet4j.exception.BACnetException;
import com.serotonin.bacnet4j.exception.ErrorAPDUException;
import com.serotonin.bacnet4j.npdu.ip.IpNetwork;
import com.serotonin.bacnet4j.npdu.ip.IpNetworkBuilder;
import com.serotonin.bacnet4j.service.acknowledgement.ReadPropertyAck;
import com.serotonin.bacnet4j.service.acknowledgement.ReadPropertyMultipleAck;
import com.serotonin.bacnet4j.service.confirmed.*;
import com.serotonin.bacnet4j.service.unconfirmed.WhoIsRequest;
import com.serotonin.bacnet4j.transport.DefaultTransport;
import com.serotonin.bacnet4j.transport.Transport;
import com.serotonin.bacnet4j.type.constructed.ReadAccessResult;
import com.serotonin.bacnet4j.type.constructed.ReadAccessSpecification;
import com.serotonin.bacnet4j.type.constructed.SequenceOf;
import com.serotonin.bacnet4j.type.enumerated.ObjectType;
import com.serotonin.bacnet4j.type.enumerated.PropertyIdentifier;
import com.serotonin.bacnet4j.type.enumerated.Segmentation;
import com.serotonin.bacnet4j.type.primitive.ObjectIdentifier;
import com.serotonin.bacnet4j.type.primitive.Real;
import com.serotonin.bacnet4j.util.DiscoveryUtils;
public class test {
public static void main(String[] args) throws Exception {
IpNetwork network = new IpNetworkBuilder().broadcastIp("192.168.1.255").localBindAddress("192.168.1.164").port(47808).build();
Transport transport = new DefaultTransport(network);
transport.setTimeout(500000);
transport.setSegTimeout(15000);
LocalDevice localDevice = new LocalDevice(21312, transport);
localDevice.getEventHandler().addListener(new DeviceEventAdapter() {
#Override
public void iAmReceived(RemoteDevice device) {
System.out.println("Discovered device " + device);
System.out.println("device Address" + device.getAddress().getMacAddress().getDescription());
localDevice.addRemoteDevice(device);
final RemoteDevice remoteDevice = localDevice.getRemoteDevice(device.getAddress());
remoteDevice.setSegmentationSupported(Segmentation.segmentedBoth);
new Thread(new Runnable() {
#Override
public void run() {
try {
try {
DiscoveryUtils.getExtendedDeviceInformation(localDevice, remoteDevice);
} catch (BACnetException e) {
e.printStackTrace();
}
System.out.println(remoteDevice.getName() + " " + remoteDevice.getVendorName() + " " + remoteDevice.getModelName() + " " + remoteDevice.getAddress() + " " + remoteDevice.getProtocolRevision() + " " + remoteDevice.getProtocolVersion());
ReadPropertyAck ack = localDevice.send(remoteDevice, new ReadPropertyRequest(remoteDevice.getObjectIdentifier(), PropertyIdentifier.objectList)).get();
SequenceOf<ObjectIdentifier> value = ack.getValue();
for (ObjectIdentifier id : value) {
List<ReadAccessSpecification> specs = new ArrayList<ReadAccessSpecification>();
specs.add(new ReadAccessSpecification(id, PropertyIdentifier.presentValue));
specs.add(new ReadAccessSpecification(id, PropertyIdentifier.units));
specs.add(new ReadAccessSpecification(id, PropertyIdentifier.objectName));
specs.add(new ReadAccessSpecification(id, PropertyIdentifier.description));
specs.add(new ReadAccessSpecification(id, PropertyIdentifier.objectType));
ReadPropertyMultipleRequest multipleRequest = new ReadPropertyMultipleRequest(new SequenceOf<ReadAccessSpecification>(specs));
ReadPropertyMultipleAck send = localDevice.send(remoteDevice, multipleRequest).get();
SequenceOf<ReadAccessResult> readAccessResults = send.getListOfReadAccessResults();
System.out.print(id.getInstanceNumber() + " " + id.getObjectType() + ", ");
for (ReadAccessResult result : readAccessResults) {
for (ReadAccessResult.Result r : result.getListOfResults()) {
System.out.print(r.getReadResult() + ", ");
}
}
System.out.println();
}
ObjectIdentifier mode = new ObjectIdentifier(ObjectType.analogValue, 11);
ServiceFuture send = localDevice.send(remoteDevice, new WritePropertyRequest(mode, PropertyIdentifier.presentValue, null, new Real(2), null));
System.out.println(send.getClass());
} catch (ErrorAPDUException e) {
System.out.println("Could not read value " + e.getApdu().getError() + " " + e);
} catch (BACnetException e) {
e.printStackTrace();
}
}
}).start();
}
#Override
public void iHaveReceived(RemoteDevice device, RemoteObject object) {
System.out.println("Value reported " + device + " " + object);
}
});
localDevice.initialize();
localDevice.sendGlobalBroadcast(new WhoIsRequest());
System.in.read();
localDevice.terminate();
}
}
On Linux we are unable to discover the devices that are running on Windows OS but the application that is running on Windows is able to discover Linux BacNet localDevice. Code is same but still unable to discover BacNet devices on Linux.
Please help us find any solution.
Issues like this (partial visibility) are often caused my a 'mismatch' of IP parameters. I notice you have hardcoded "192.168.1.255". Is this really the broadcast IP address from the PI's perspective?
Resolved the problem by removing the broadcast and LocalBindAddress.
Code below works and sends message at scheduled time but I think it isn't a good solution to open new socket every time timer executes scheduled task. What I would like is to open socket in run method only once and access it in SendMessage class whenever new instance of class is made in timer. That way it doesn't work, it only sends one message and then stops sending. Also I would be happy for some critics about code or tips for making it thread safe.
public class Client implements Runnable{
// Client Constructor here
#Override
public void run(){
//SENDS ONLY ONE MESSAGE
pitcherSocket = new Socket(InetAddress.getByName(hostname), port);
Timer timer = new Timer();
timer.schedule(new SendMessage(), 0, 1000/mps);
}
private class SendMessage extends TimerTask{
private int id;
#Override
public void run() {
try
{ // THIS WORKS FINE, SENDS MESSAGES AT SCHEDULED TIME
pitcherSocket = new Socket(InetAddress.getByName(hostname), port);
OutputStream outToServer = pitcherSocket.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.writeInt(id);
out.flush();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
}
EDIT: WHOLE CODE
CLIENT
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
public class Pitcher implements Runnable{
private int port;
private int mps;
private int size;
private String hostname;
private List<Integer> messageIds = Collections.synchronizedList(new ArrayList<Integer>());
private Socket pitcherSocket;
//constatns, integer is 4 bytes, long is 8 bytes
private static final int INT_SIZE = 4;
private static final int LONG_SIZE = 8;
public Pitcher(int port, int mps, int size, String hostname) {
this.port = port;
this.mps = mps;
this.size = size;
this.hostname = hostname;
}
#Override
public void run(){
System.out.println("Pitcher running...");
System.out.println();
Timer timer = new Timer();
timer.schedule(new SendMessage(), 0, 1000/mps);
timer.schedule(new DisplayStatistics(), 0, 1000/mps);
}
//Nested class that sends messages
private class SendMessage extends TimerTask{
private int numberOfSentMessages = 0;
private int id;
#Override
public void run() {
try {
pitcherSocket = new Socket(InetAddress.getByName(hostname), port);
OutputStream outToServer = pitcherSocket.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
//send message size
out.writeInt(size);
//message id is same as number of the sent message
id = numberOfSentMessages + 1;
out.writeInt(id);
messageIds.add(id);
//get system timestamp
long currentTimestamp = System.currentTimeMillis();
out.writeLong(currentTimestamp);
//fill in the rest-
byte[] rest = new byte[size - 2 * INT_SIZE - LONG_SIZE]; //message size(default 300 bytes) - size(4 bytes) - message id(4 bytse) - timestamp(8 bytes)
out.write(rest);
out.flush();
numberOfSentMessages++;
InputStream inFromServer = pitcherSocket.getInputStream();
DataInputStream in = new DataInputStream(inFromServer);
Integer catcherMessageSize = in.readInt();
Integer catcherId = in.readInt();
long catcherTimestamp = in.readLong();
System.out.println("Sent message: " + size + " " + id + " " + currentTimestamp + "...");
System.out.println("Received message: " + catcherMessageSize + " " + catcherId + " " + catcherTimestamp + "...");
System.out.println();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
}
SERVER
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
public class Catcher implements Runnable{
private int port;
private String bind;
private ServerSocket serverSocket;
//constatns, integer is 4 bytes, long is 8 bytes
private static final int INT_SIZE = 4;
private static final int LONG_SIZE = 8;
public Catcher(int port, String bind) {
this.port = port;
this.bind = bind;
}
#Override
public void run() {
System.out.println("Catcher running...");
System.out.println();
try {
serverSocket = new ServerSocket(port, 100, InetAddress.getByName(bind));
}
catch (IOException e1) {
e1.printStackTrace();
}
while(true){
try
{
Socket server = serverSocket.accept();
DataInputStream in = new DataInputStream(server.getInputStream());
Integer pitcherMessageSize = in.readInt();
Integer pitcherId = in.readInt();
long pitcherTimestamp = in.readLong();
DataOutputStream out = new DataOutputStream(server.getOutputStream());
//message id and size are sent back
out.writeInt(pitcherMessageSize);
out.writeInt(pitcherId);
//send back current time
long currentTimestamp = System.currentTimeMillis();
out.writeLong(currentTimestamp);
//fill in the rest
byte[] rest = new byte[pitcherMessageSize - 2 * INT_SIZE - LONG_SIZE]; //message size(default 300 bytes) - size(4 bytes) - message id(4 bytes) - timestamp(8 bytes)
out.write(rest);
out.flush();
System.out.println("Received message: " + pitcherMessageSize + " " + pitcherId + " " + pitcherTimestamp + "...");
System.out.println("Sent message: " + pitcherMessageSize + " " + pitcherId + " " + currentTimestamp + "...");
System.out.println();
//server.close();
}
catch(SocketTimeoutException s){
System.out.println("Socket timed out!");
break;
}
catch(IOException e){
e.printStackTrace();
break;
}
}
}
}
Have you thought about making both socket and the DataOutputStream member variables of SendMessage. This is some code to give you a rough start. You will probably want to put some enhancements like checking whether the socket is open and being able to create a new one if the current one is closed...
private class SendMessage extends TimerTask {
private int id = 10;
private Socket pitchSocket;
private DataOutputStream out;
public SendMessage(Socket socket) {
this.pitchSocket = socket;
try{
out = new DataOutputStream(pitchSocket.getOutputStream());
} catch(IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
try {
out.writeInt(id);
out.flush();
} catch(IOException e) {
e.printStackTrace();
}
}
}
After being able to view the whole code I think that you definitely have some threading issues, though I think they are more heavily on the server side rather than the client side. Your server is single threaded. That means that you can only deal with one request at a time. You want a multithreaded server. I've refactored your code to create an example of Catcher which is multithreaded. I'm using the Thead class to do all of this which may be a little old fashioned. You might want to take a look at java.util.concurrent, they will probably have a more up to date.
package clientserver;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
public class Catcher implements Runnable{
private int port;
private String bind;
private ServerSocket serverSocket;
public Catcher(int port, String bind) {
this.port = port;
this.bind = bind;
}
#Override
public void run() {
System.out.println("Catcher running...");
System.out.println();
try {
serverSocket = new ServerSocket(port, 100, InetAddress.getByName(bind));
}
catch (IOException e1) {
e1.printStackTrace();
}
while(true){
try
{
new Thread(new CatcherHandler(serverSocket.accept())).start();
Thread.sleep(1000);
}
catch(SocketTimeoutException s){
System.out.println("Socket timed out!");
break;
}
catch(IOException e){
e.printStackTrace();
break;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] argv){
new Thread( new Catcher(8093, "localhost")).start();;
}
}
class CatcherHandler implements Runnable{
Socket server;
DataOutputStream out;
DataInputStream in;
private static final int INT_SIZE = 4;
private static final int LONG_SIZE = 8;
public CatcherHandler(Socket server) {
super();
this.server = server;
try {
in = new DataInputStream(server.getInputStream());
out = new DataOutputStream(server.getOutputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void run() {
try{
if(in.available() > 0){
Integer pitcherMessageSize = in.readInt();
Integer pitcherId = in.readInt();
long pitcherTimestamp = in.readLong();
//message id and size are sent back
out.writeInt(pitcherMessageSize);
out.writeInt(pitcherId);
//send back current time
long currentTimestamp = System.currentTimeMillis();
out.writeLong(currentTimestamp);
//fill in the rest
byte[] rest = new byte[pitcherMessageSize - 2 * INT_SIZE - LONG_SIZE]; //message size(default 300 bytes) - size(4 bytes) - message id(4 bytes) - timestamp(8 bytes)
out.write(rest);
out.flush();
System.out.println("Received message: " + pitcherMessageSize + " " + pitcherId + " " + pitcherTimestamp + "...");
System.out.println("Sent message: " + pitcherMessageSize + " " + pitcherId + " " + currentTimestamp + "...");
System.out.println();
Thread.sleep(1000);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{}
//server.close();
}
}
Additionally I refactored your client to be able to use one socket and be tread safe. Now SendMessage takes in a DataInputStream and a DataOutputSteam as it's arguments.
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
public class Pitcher implements Runnable{
private int port;
private int mps;
private int size;
private String hostname;
private List<Integer> messageIds = Collections.synchronizedList(new ArrayList<Integer>());
private Socket pitcherSocket;
private DataOutputStream out;
private DataInputStream in;
//constatns, integer is 4 bytes, long is 8 bytes
private static final int INT_SIZE = 4;
private static final int LONG_SIZE = 8;
public Pitcher(int port, int mps, int size, String hostname) {
this.port = port;
this.mps = mps;
this.size = size;
this.hostname = hostname;
try {
this.pitcherSocket = new Socket(InetAddress.getByName(hostname), port);
out = new DataOutputStream(pitcherSocket.getOutputStream());
in = new DataInputStream(pitcherSocket.getInputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] argv) throws Exception{
for(int i = 0; i < 10; i++){
new Thread(new Pitcher(8093, 1, 200, "localhost")).start();
Thread.sleep(1000);
}
Thread.sleep(10000);
}
#Override
public void run(){
System.out.println("Pitcher running...");
System.out.println();
Timer timer = new Timer();
timer.schedule(new SendMessage(out, in), 0, 1000);
//timer.schedule(new DisplayStatistics(), 0, 1000);
}
//Nested class that sends messages
private class SendMessage extends TimerTask{
private int numberOfSentMessages = 0;
private int id;
private DataOutputStream out;
private DataInputStream in;
public SendMessage(DataOutputStream out, DataInputStream in){
this.out = out;
this.in = in;
}
#Override
public void run() {
try {
long currentTimestamp = 0L;
synchronized(out){
//send message size
out.writeInt(size);
//message id is same as number of the sent message
id = numberOfSentMessages + 1;
out.writeInt(id);
messageIds.add(id);
//get system timestamp
currentTimestamp = System.currentTimeMillis();
out.writeLong(currentTimestamp);
//fill in the rest-
byte[] rest = new byte[size - 2 * INT_SIZE - LONG_SIZE]; //message size(default 300 bytes) - size(4 bytes) - message id(4 bytse) - timestamp(8 bytes)
out.write(rest);
out.flush();
}
numberOfSentMessages++;
long catcherTimestamp = 0L;
Integer catcherMessageSize;
Integer catcherId;
synchronized(in){
catcherMessageSize = in.readInt();
catcherId = in.readInt();
catcherTimestamp = in.readLong();
}
System.out.println("Sent message: " + size + " " + id + " " + currentTimestamp + "...");
System.out.println("Received message: " + catcherMessageSize + " " + catcherId + " " + catcherTimestamp + "...");
System.out.println();
Thread.sleep(1000);
}catch(IOException e)
{
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
The Java Socket class is not thread safe. To have multiple threads access the same Socket object you would need to synchronize their actions. This could be done by providing all your SendMessage-threads with a common object that would then act as a lock. You would need an object for each socket operation you are planning to use (e.g. read and write). Then, refactor every action that does a call to the Socket object into separate methods and synchronize them around that object. E.g. for the read operation you could have a method called read() inside SendMessage that calls Socket.read and synchronize this method around the lock-object for read.
private class SendMessage extends TimerTask{
private Object readLock;
private Socket socket;
public SendMessage(Object readLock, Socket socket) {
this.readLock = readLock;
this.socket = socket;
}
public void readFromSocket() {
synchronized(readLock) {
socket.read();
}
}
#Override
public void run() {
readFromSocket();
// do other stuff
}
}
I am creating a socket connection with a client utilizing android studio. I can successfully make a connection between the mobile device and the server, and my first debug message (Log.d("While Debugger", line)) successfully shows the input data from the server. However, the arraylist does not appear to adding the results, and my other debug messages are not providing any output!
To clarify further, when I call the returnData() method the temperature array is returned as null.
Any help will be much appreciated, and I will do my best to answer any questions asked of what I've written. Thanks!
package com.mycompany.myfirstapp;
import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
/**
* Created by seank on 15/07/2015.
*/
public class SocketExample {
ArrayList<Double> temperature = new ArrayList<Double>();
public SocketExample() throws IOException {
String serverHostname = new String ("192.168.1.143");
System.out.println ("Attemping to connect to host " +
serverHostname + " on port 10007.");
Socket echoSocket = null;
PrintWriter out = null;
BufferedReader in = null;
Log.d("Here", "Got to the streams");
try {
echoSocket = new Socket(serverHostname, 10007);
in = new BufferedReader(new InputStreamReader(
echoSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host: " + serverHostname);
Log.e("Here","Don't know about host: " + serverHostname);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for "
+ "the connection to: " + serverHostname);
Log.e("Here","Couldn't get I/O for "
+ "the connection to: " + serverHostname);
System.exit(1);
}
String line;
while( (line = in.readLine()) != null ) {
Log.d("While Debugger", line);
Double value = Double.parseDouble(line);
temperature.add(value);
}
if(temperature.size() == 0) {
Log.d("Numbers", "size = 0");
}
else {
Log.d("Numbers", String.valueOf(temperature.size()));
}
if(String.valueOf(temperature.size()) == null) {
Log.e("Numbers", "The temperature size is a null value");
}
// Close our streams
in.close();
out.close();
echoSocket.close();
}
public ArrayList<Double> returnData() {
return temperature;
}
public static void main(String[] args) throws IOException {
SocketExample socket = new SocketExample();
}
}
I think that, your program is blocking in the while loop, so your next debug is not executed.
You can try to add below code into the your while loop
if(temperature.size() == 0) {
Log.d("Numbers", "size = 0");
}
else {
Log.d("Numbers", String.valueOf(temperature.size()));
}
I am planning to do a java onvif application. I have created a new project and generated sources from devicemgmt.wsdl.Also generated the classes from remote discovery.wsdl.
How can I discover a device in a network using theses generated classes?
Thanks for any help.
devicemgmt.wsdl is not related to discovery process, the ONVIF discovery process is based on http://specs.xmlsoap.org/ws/2005/04/discovery it use SOAP over UDP.
If you are using apache-cxf, this can be achieve using
org.apache.cxf.ws.discovery.WSDiscoveryClient
A simple sample code could be :
import java.util.List;
import javax.xml.ws.EndpointReference;
import org.apache.cxf.ws.discovery.WSDiscoveryClient;
public class Main
{
public static void main(String[] args)
{
WSDiscoveryClient client = new WSDiscoveryClient();
client.setVersion10(); // use WS-discovery 1.0
client.setDefaultProbeTimeout(1000); // timeout 1s
System.out.println("Probe:" + client.getAddress());
List<EndpointReference> references = client.probe();
System.out.println("Nb answsers:" + references.size());
for (EndpointReference ref : references)
{
System.out.println(ref.toString());
}
}
}
I had the same problem, CXF is simply to big, please check my approach: JavaWsDiscovery at https://github.com/thhart/javaWsDiscovery.
It uses a simple network probe as suggested by Onvif standards to be able to identify any devices on your local network, following line will return you all available devices:
final Collection urls = DeviceDiscovery.discoverWsDevicesAsUrls("^http$", ".onvif.");
Simple and complete example pure Java
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
/**
*
* #author Ronald
*/
public class TestDiscoveryPureJava {
public static void main(String cor[]) throws SocketException{
discoverWsDevices();
}
public static void discoverWsDevices() throws SocketException {
final int WS_DISCOVERY_PORT = 3702;
final String WS_DISCOVERY_ADDRESS_IPv4 = "239.255.255.250";
Thread thread = new Thread() {
#Override
public void run() {
final String probe = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:a=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\">\n" +
" <s:Header>\n" +
" <a:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</a:Action>\n" +
" <a:MessageID>uuid:f0ded492-301a-4891-882b-cb2d7cac2e45</a:MessageID>\n" +
" <a:ReplyTo>\n" +
" <a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address>\n" +
" </a:ReplyTo>\n" +
" <a:To s:mustUnderstand=\"1\">urn:schemas-xmlsoap-org:ws:2005:04:discovery</a:To>\n" +
" </s:Header>\n" +
" <s:Body>\n" +
" <Probe xmlns=\"http://schemas.xmlsoap.org/ws/2005/04/discovery\">\n" +
" <d:Types xmlns:d=\"http://schemas.xmlsoap.org/ws/2005/04/discovery\" xmlns:dp0=\"http://www.onvif.org/ver10/network/wsdl\">dp0:Device</d:Types>\n" +
" </Probe>\n" +
" </s:Body>\n" +
"</s:Envelope>";
DatagramSocket datagramSocket = null;
try {
datagramSocket = new DatagramSocket();
datagramSocket.setBroadcast(true);
datagramSocket.setSoTimeout(9000);
} catch (SocketException e) {
System.out.println( "In discoverWsDevices datagram socket exception" + datagramSocket);
e.printStackTrace();
}
byte[] soapMessageByteArray = probe.getBytes();
DatagramPacket datagramPacketSend = null;
try {
datagramPacketSend = new DatagramPacket(
soapMessageByteArray,
soapMessageByteArray.length,
InetAddress.getByName(WS_DISCOVERY_ADDRESS_IPv4),
WS_DISCOVERY_PORT);
} catch (UnknownHostException e) {
System.out.println("Unknown host in send packet");
e.printStackTrace();
}
try {
System.out.println("Send package");
datagramSocket.send(datagramPacketSend);
System.out.println("package sent");
} catch (IOException e) {
System.out.println("In discoverWsDevices datagram socket IOException send " + datagramSocket);
e.printStackTrace();
}
System.out.println("Sending data");
System.out.println(datagramPacketSend.getAddress().getHostName()+":"+WS_DISCOVERY_PORT);
List<ByteArrayInputStream> probeMatches = new ArrayList<>();
while (true) {
byte[] responseMessageByteArray = new byte[9000];
DatagramPacket datagramPacketRecieve = new DatagramPacket(responseMessageByteArray,responseMessageByteArray.length);
try {
System.out.println("Waiting response...");
datagramSocket.receive(datagramPacketRecieve);
} catch (SocketTimeoutException e) {
datagramSocket.close();
System.out.println("In discoverWsDevices datagram socket timeout exception");
break;
} catch (IOException e) {
System.out.println("In discoverWsDevices datagram socket ioexception");
e.printStackTrace();
break;
}
probeMatches.add(new ByteArrayInputStream(datagramPacketRecieve.getData(), 0, datagramPacketRecieve.getLength()));
}
for (ByteArrayInputStream input : probeMatches) {
byte[] bytes = new byte[input.available()];
input.read(bytes, 0, input.available());
String stream = new String(bytes);
System.out.println("stream" + stream);
}
}
};
thread.start();
}
}