I have a stream of video. And every frame I need to send a small json file with data from that frame, speed it´s crucial. Whats the best way to do this?
My Server is something like this. Waits for a json file and then has to send that json file to a python application.
public class ServerClass {
public static void main(String[] args) {
Marcoserver mimarco=new Marcoserver();
}
}
class Marcoserver implements Runnable {
public Marcoserver(){
Thread miHilo = new Thread(this);
miHilo.start();
}
public void run() {
try {
ServerSocket server = new ServerSocket(7777);
while (true) {
Socket miSocket = server.accept();
BufferedReader entrada = new BufferedReader(new InputStreamReader(miSocket.getInputStream(), "UTF8"));
String mensaje = entrada.readLine();
JSONObject obj;
obj = new JSONObject(mensaje);
System.out.println(obj);
ConectorSocket cntor = new ConectorSocket("localhost", 6363);
cntor.Conectar();
cntor.Send(mensaje);
cntor.Close();
miSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class ConectorSocket{
private String host;
private int port;
Socket sockSend;
public ConnectClass(String hst, int prt ) {
this.host = hst;
this.port = prt;
}
public void Conectar() {
this.sockSend = new Socket(this.host, this.port);
}
public void Send(String mensaje) {
DataOutputStream flujo_salida = new DataOutputStream(sockSend.getOutputStream());
flujo_salida.writeBytes(mensaje);
flujo_salida.close();
}
public boolean Close() {
this.sockSend.close();
}
}
This is the python app simplified:
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind(('localhost', 6666))
serversocket.listen()
while True:
connection, address = serversocket.accept()
buf = connection.recv(2048)
if len(buf) > 0:
print(buf.decode())
My problem is that the python app prints incomplete information such as:
{"keyword"
{"keyword": [[14, 1, -1]]}
{"keyword": [[14,
instead of:
{"keyword":[]}
{"keyword":[[14,1,-1]]}
{"keyword":[[14,2,-1]]}
There's nothing wrong with your Java code, but your Python code is not good:
while True:
connection, address = serversocket.accept()
buf = connection.recv(2048)
if len(buf) > 0:
print(buf.decode())
That will print just the first received TCP packet for each connection.
You need to continue calling recv until it returns 0:
while True:
connection, address = serversocket.accept()
msg = []
while True:
buf = connection.recv(65536)
if (len(buf) == 0):
break
msg.append(buf)
print(''.join(msg))
connection.close()
You also need to close each connection.
Related
I have some problems with the connection between my EV3 and my Android-Device.
I am able to receive Data with my EV3, but I can't send.
I have signed up with my Github account if you like to see the App.
Here is my Code:
public class Bluetooth {
public static int speed = 100;
public static BTConnector connector;
public static NXTConnection connection;
public static void main(String[] args) throws IOException {
openConnection();
Thread moveWithBluetoothThread = new Thread(new moveWithBluetooth());
moveWithBluetoothThread.start();
}
public static void openConnection() {
connector = new BTConnector();
LCD.drawString("Waiting for Connecrion", 3, 1);
connection = connector.waitForConnection(0, NXTConnection.RAW);
LCD.clear();
LCD.drawString("Connected", 3, 5);
}
}
class moveWithBluetooth implements Runnable {
#Override
public void run() {
while (true) {
InputStream is = Bluetooth.connection.openInputStream();
BufferedReader dis = new BufferedReader(new InputStreamReader(is), 1);
OutputStream os = Bluetooth.connection.openOutputStream();
BufferedWriter dos = new BufferedWriter(new OutputStreamWriter(os), 1);
try {
byte[] b;
for (int i = 0; i < 100; i++) {
String n = dis.readLine();
System.out.println(n);
b = n.getBytes();
Bluetooth.connection.write(b, b.length);
Thread.sleep(10);
dos.write(n);
dos.flush();
}
dis.close();
dos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
I found out, that there was no Problem with my EV3. That means, you can use this code. If you are having the same Problem, here is my solution:
The Problem was the Library I use in my Application. At the "Tssues"-Tab of Github was my Problem. The library waits until there is a complete Transmission, but the EV3 sends a permanent Stream, so I just had to add \r\n at the end of my Transmission. My final Code looked like that:
byte[] b = (n + "\r\n").getBytes();
Bluetooth.connection.write(b, b.length);
I write my own Java FTP server. Until recently I used PUttY to debug my control telnet connection and everything seemed fine - I had successful two-way communication. Now I try to debug my server with FileZilla, but it does not seem to read my text, nor to send some to server, so it just hangs and wait for something.
Control connection class
public class ControlConnection extends Thread {
private enum OperationMode {
ACTIVE, PASSIVE
}
private final Map<String, Supplier<String>> COMMANDS;
private String[] userTokens;
private User user;
private String userLogin;
private boolean authenticated;
private boolean dataConnected;
private boolean userExists;
private final Socket socket;
private DataInputStream inputStream;
private DataOutputStream outputStream;
private DataConnection ftpSession;
private OperationMode operationMode;
private String errorMessage;
public ControlConnection(Socket socket) {
super(ControlConnection.class.toString());
this.socket = socket;
// constants initialization
authenticated = false;
dataConnected = false;
// commands initialization
COMMANDS = new HashMap<>();
// commands init
}
#Override
public void run() {
try {
inputStream = new DataInputStream(socket.getInputStream());
outputStream = new DataOutputStream(socket.getOutputStream());
sendGreetings();
IOProcessing.writeBytes(outputStream, pasvCommand());;
boolean running = true;
while (running) {
sendGreetings();
String input = IOProcessing.readBytes(inputStream);
if (!(input.equals("")))
System.out.println(input);
if (!checkInput(input))
continue;
userTokens = input.split(" ");
String command = userTokens[0].toUpperCase();
String answer = COMMANDS.get(command).get();
outputStream.writeBytes(answer);
}
}
catch (IOException e) {
System.err.println(e);
System.exit(-1);
}
}
private boolean commonCheck() {
// some checks
return true;
}
private String getErrorMessage() {
return errorMessage;
}
public void sendGreetings() {
String greetings = String.format("220 Control connection established: %s", getConnectionInfo());
IOProcessing.writeBytes(outputStream, greetings);
}
public String getConnectionInfo() {
String info = String.format("%s: %d %s",
socket.getInetAddress().toString(), socket.getPort(), user != null ? user.getUsername(): "");
return info;
}
// input/output proccessing functions
public boolean checkInput(String input) {
// checks
return true;
}
// commands functions
private String pasvCommand() {
if (operationMode == OperationMode.PASSIVE) {
errorMessage = "Already in passive mode.%n";
return errorMessage;
}
String answer;
new ListenToSocket().start();
answer = String.format("227 Entering Passive Mode (%s, %d)",
"127.0.0.1", DataConnection.PORT);
operationMode = OperationMode.PASSIVE;
return answer;
}
private class ListenToSocket extends Thread {
public ListenToSocket() {
}
#Override
public void run() {
try {
ServerSocket ftpSocket =
new ServerSocket(DataConnection.PORT);
ftpSession =
DataConnection.getDataConnection(ftpSocket.accept());
if (ftpSession != null) {
ftpSession.start();
dataConnected = true;
String greetings = "Data connection established: " + ftpSession.getConnectionInfo();
IOProcessing.writeBytes(outputStream, greetings);
} else {
dataConnected = false;
}
} catch (IOException e) {
System.out.print(e);
}
}
}
also, server does not get user credentials, entered in FileZilla - input from server is always empty
IOProcessing class
public class IOProcessing {
private static final Charset UTF8_CHARSET;
static {
UTF8_CHARSET = Charset.forName("UTF-8");
}
public static String readBytes(DataInputStream inputStream) {
String result = "";
try {
int len = inputStream.available();
if (len == 0) {
return result;
}
byte[] byteInput = new byte[len];
inputStream.readFully(byteInput, 0, len);
result = new String(byteInput, "UTF-8").trim();
} catch (IOException e) {
System.err.println(e);
}
return result;
}
output FileZlla log
Status: Resolving address of localhost
Status: Connecting to [::1]:21...
Status: Connection established, waiting for welcome message.
You didn't show us the writeBytes. So I can only guess that you are not sending \r\n after the messages sent to the client. Particularly after the welcome message. So FileZilla keeps waiting forever for it, as any FTP client would do.
I have implemented Android App - Server side application. The Android app communicate with the server to get authtenticated by the smart card. When I click a button in the App a TCP connection is built and messages are being exchanged until the protocol ends so far so good. Currently I am facing problem when I click the button in the app again. The same process is beig passed through
but the retrieved data from the smart card are different.
In the SmartCard class --> forwardMessage():
--> First button clicking in the Android App --> first clientSocket:
I am getting this byte [0, -92, 2, 12, 2, 0, 2] array as in the screenshot and when calling channel.transmit(new CommandAPDU(array)); I am getting the right response [-112,0]
--> Second button clicking in the Android App --> second clientSocket (without run the server application neu)
I am getting this byte [0, -92, 2, 12, 2, 0, 2] array as in the screenshot and when calling channel.transmit(new CommandAPDU(array)); I am getting the right response [106,-126]
This result [106,-126] should be like the one of the first clientSocket also [-112,0]. As a result of this retrieved data [106,-126] from the smart card the protocol is not being executed to the end.
I have tried to call the disconnect() of the Card class inside the disconnect() of the SmartCard but I am
I appreciate any help!
the first clientsocket data
the second clientsocket data
Android App --> Server --> Card Reader
Server class
public class Server {
private final static int RECEIVE_BUFFER_LENGTH = 512;
public final static int MESSAGE_MAXIMUM_LENGTH = 256;
private final static int MESSAGE_HEADER_LENGTH = 8;
private static InputStream bufferedInputStream = null;
private static OutputStream outputStream = null;
private static SmartCard smartCard = null;
public static void main(String args[]) throws Exception {
ServerSocket serverSocket = new ServerSocket(27015);
System.out.println("SS construction of server socket");
System.out.println("SS listenting for incoming connection on port 27015");
while (true) {
Socket clientSocket = serverSocket.accept();
Server.bufferedInputStream = new BufferedInputStream(clientSocket.getInputStream());
Server.outputStream = clientSocket.getOutputStream();
Server.smartCard = new SmartCard();
Server.handleConnection();
Server.bufferedInputStream.close();
Server.outputStream.close();
Server.smartCard = null;
clientSocket.close();
System.out.println("Smart card instance was deleted ");
System.out.println("--------------------- Finished ---------------------------");
}
}
private static void handleConnection() throws IOException {
ByteBuffer receiveBuffer = ByteBuffer.allocate(Server.RECEIVE_BUFFER_LENGTH);
int readBytes = 0;
while (true) {
readBytes = Server.bufferedInputStream.read(receiveBuffer.array(), receiveBuffer.position(),
receiveBuffer.remaining());
System.out.println("readBytes: " + readBytes);
if (readBytes < 0) {
break;
}
//Here I am reading the received bytes and communicating with the Smart card.
}
}
}
}
SmartCard
public class SmartCard {
public Card card;
private String protocol;
public void connect(String preferredProtocol) {
Card cardTemp = null;
this.protocol = preferredProtocol;
try {
TerminalFactory factory = TerminalFactory.getDefault();
List<CardTerminal> terminals = factory.terminals().list();
CardTerminal terminal = terminals.get(0);
System.out.println("Reader name: " + terminal.getName());
if (preferredProtocol.equals(ProtocolType.SC_T0.getProtocolName())) {
cardTemp = terminal.connect(preferredProtocol);
} else if (preferredProtocol.equals(ProtocolType.SC_T1.getProtocolName())) {
cardTemp = terminal.connect(preferredProtocol);
}
System.out.println("SC connect --> SCARD Protocol " + preferredProtocol);
this.card = cardTemp;
} catch (CardException e) {
e.printStackTrace();
}
}
private boolean isConnect() {
if (this.card != null) {
return true;
} else {
return false;
}
}
public void disconnect() throws CardException {
if (this.isConnect()) {
this.card = null;
//this.card.disconnect(false);
System.out.println("SC disconnect()");
}
}
private void reconnect(String preferredProtocol) {
if (!this.isConnect()) {
this.connect(preferredProtocol);
}
}
public byte[] requestATR() {
ATR atr = this.card.getATR();
if (atr.getBytes().length > 0xFF) {
throw new IllegalArgumentException(
"Package too big, not supported with protocol -> Answer To Test byte array is too big!");
}
return atr.getBytes();
}
public byte[] forwardMessage(byte[] array) throws CardException {
try {
if (!this.isConnect()) {
this.reconnect(this.protocol);
System.out.println("SC reconnect()");
}
Cg2AapiServer.printData(array, array.length, SmartCard.OPERATOR, Cg2AapiServer.RECEIVE);
CardChannel channel = this.card.getBasicChannel();
System.out.println("data from the client socket: " + Arrays.toString(array));
ResponseAPDU responseAPDU = channel.transmit(new CommandAPDU(array));
byte[] byteArray = responseAPDU.getBytes();
System.out.println("retrieved data from the smart card: " + Arrays.toString(byteArray));
if (responseAPDU.getBytes().length > 0xFF) {
throw new IllegalArgumentException("Package too big, not supported with protocol.");
}
Cg2AapiServer.printData(responseAPDU.getBytes(), responseAPDU.getBytes().length, SmartCard.OPERATOR,
Cg2AapiServer.TRANSMIT);
return responseAPDU.getBytes();
} catch (CardException e) {
e.printStackTrace();
}
return null;
}
}
To get it work I had to add the this.card.disconnect(false); method to the disconnect() method in the smart Card like this:
public void disconnect() throws CardException {
if (this.isConnect()) {
// this.card = null;
this.card.disconnect(false);
System.out.println("SC disconnect()");
}
}
i am having a problem with private messages in java. I ask the user for a "name" when they launch the Client, and it is a variable in ChatClient.java file. I have made it "public", but when i try to call it in the ChatServer.java it says "cannot find symbol". Any help with that? Also in this snippet i am searching for the right "name" from users, should there be anything defiying the "i" name? (like i.name or some sort of connection between the current client and their name).
ChatServer problematic part
public void sendPrivate(String message) throws Exception {
Iterator<Socket> i = clients.iterator();
StringTokenizer st = new StringTokenizer(message.substring(7,message.length()),", ");
String realMessage = st.nextToken();
String to = st.nextToken();
while (i.hasNext()) {
Socket socket = (Socket) i.next();
try {
if (name.equals(to)){
DataOutputStream out = new DataOutputStream(socket.getOutputStream()); // create output stream for sending messages to the client
out.writeUTF(realMessage); // send message to the client
}
}
catch (Exception e) {
System.err.println("[system] could not send message to a client");
e.printStackTrace(System.err);
}
}
}
ChatClient part where the user inputs their "name"
public class ChatClient extends Thread
{
public String name;
protected int serverPort = 8888;
public static void main(String[] args) throws Exception {
new ChatClient();
}
public ChatClient() throws Exception {
Socket socket = null;
DataInputStream in = null;
DataOutputStream out = null;
//whitelistaned
String[] whitelist = {"Bob", "Frank", "Goliath", "Zealot", "Bruce Wayne"};
int aliUstrezas = 0;
//common courtesy
System.out.println();
System.out.println("Would you fancy in telling me your name, sir ?");
System.out.println("Current whitelist: {'Bob', 'Frank', 'Goliath', 'Zealot', 'Bruce Wayne'} ");
Scanner sc = new Scanner(System.in);
name = sc.nextLine();
ChatServer does not instantiate a object of type ChatClient, so it does not matter if name is public or not, it can not magically read variables from any arbitrary object.
I'm trying to send and object over udp by first serializing it and then deserializing it on the other end. I thought this would be trivial since I have sent other data over udp before and serialized stuff to the files etc.
I have debugged thing some time now and I keep getting EOFException on the receiving end. Packets arrive properly but somehow deserialization fails. I'm not sure if the mistake is in sender or receiver. I suppose the problem might be about the receiver not knowing the size of the packet.
Here is my sender class:
package com.machinedata.sensordata;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import android.content.Context;
import android.util.Log;
import com.machinedata.io.DataSerializer;
import com.machinedata.io.ManagerUdpPacket;
/**
* This class sends udp-packets. It is used to send driver's information to the manager tablet.
* #author tuomas
*
*/
public class UdpSender
{
private final int MANAGER_PORT = 1234;
private String ip = "192.168.11.50"; //tablet's IP
private DatagramSocket sock = null;
private InetAddress host;
private String mType;
private DataSerializer dataser;
public UdpSender(Context context)
{
try
{
sock = new DatagramSocket();
host = InetAddress.getByName(ip); //tabletin ip
}
catch(Exception e)
{
System.err.println("Exception alustettaessa senderia" + e);
}
dataser = new DataSerializer(context);
}
/**
* With this function we can send packets about our machine to the manager to
* see in the fleet-view.
*/
public void sendToManager(ManagerUdpPacket managerUdp)
{
//serialize
Log.v("sendudp", "Send a packet: " + managerUdp.getDriver());
//serialize
byte[] data = dataser.serializeManagerPacket(managerUdp);
//send
try
{
DatagramPacket dp = new DatagramPacket(data , data.length , host , MANAGER_PORT);
sock.send(dp);
}
catch(IOException e)
{
System.err.println("IOException senderissa " + e);
}
}
public void close()
{
sock.close();
}
}
Here is the serialization function:
/**
* Serializes packet to be sent over udp to the manager tablet.
*/
public byte[] serializeManagerPacket(ManagerUdpPacket mp)
{
try
{
ByteArrayOutputStream baos = new ByteArrayOutputStream(2048);
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(mp);
oos.close();
// get the byte array of the object
byte[] obj= baos.toByteArray();
baos.close();
return obj;
}
catch(Exception e) {
e.printStackTrace();
}
return null;
}
Packet receiver class
public class UdpReceiver {
private DatagramSocket clientSocket;
private byte[] receiveData;
private final int timeout = 1;
/**
* Create a receiver.
* #param port Port to receive from.
* #param signCount Number of signals in a packet
*/
public UdpReceiver(int port)
{
//receiveData = serializeManagerPacket(new ManagerUdpPacket("asd", new MachineData(1, 2, "asd", "modelName"), 1,2,3,4,5.0,null));
try{
clientSocket=new DatagramSocket(port);
clientSocket.setReceiveBufferSize(2048);
clientSocket.setSoTimeout(timeout);
}catch(SocketException e){
Log.e("ERR", "SocketException in UdpReceiver()");
}
}
public void close()
{
clientSocket.close();
}
/**
* Receive a data packet and split it into array.
* #param data Array to put data in, must be correct size
* #return True on successful read, false otherwise
*/
public ManagerUdpPacket receive()
{
//receive a packet
DatagramPacket recvPacket = new DatagramPacket(receiveData, receiveData.length);
try{
clientSocket.receive(recvPacket);
}catch(IOException e){
Log.e("ERR", "IOException in UdpReceiver.receive");
return null;
}
ManagerUdpPacket obj = deserializeManagerPacket(receiveData);
if (obj != null)
Log.v("udpPacket", "UDP saatu: " + obj.getDriver());
return obj;
}
/**
* Deserialize the udp-packet back to readable data.
* #param data
* #return
*/
public ManagerUdpPacket deserializeManagerPacket(byte[] data)
{
try
{
ObjectInputStream iStream = new ObjectInputStream(new ByteArrayInputStream(data));
ManagerUdpPacket obj = (ManagerUdpPacket) iStream.readObject();
iStream.close();
return obj;
}
catch(Exception e)
{
e.printStackTrace();
}
return null;
}
}
Thread which listens packets in receiving end:
dataStreamTask = new TimerTask()
{
public void run()
{
if (currentlyStreaming)
{
ManagerUdpPacket mp = udpReceiver.receive();
if(mp != null)
{
Log.v("log", "Paketti saatu! " + mp.getDriver());
}
//stop thread until next query
try {
synchronized(this){
this.wait(queryInterval);
}
} catch (InterruptedException e) {
Log.e("ERR", "InterruptedException in TimerTask.run");
}
}
}
And finally the class I'm sending over the UDP:
public class ManagerUdpPacket implements Serializable
{
private static final long serialVersionUID = 9169314425496496555L;
private Location gpsLocation;
private double totalFuelConsumption;
private long operationTime;
//workload distribution
private long idleTime = 0;
private long normalTime = 0;
private long fullTime = 0;
private int currentTaskId;
private String driverName;
String machineModelName = "";
String machineName = "";
int machineIconId = -1;
int machinePort = -1;
public ManagerUdpPacket(String driver, MachineData machine, int currentTaskId, long idleTime, long fullTime, long operationTime, double fuelConsumption, Location location)
{
driverName = driver;
this.currentTaskId = currentTaskId;
this.idleTime = idleTime;
this.fullTime = fullTime;
this.operationTime = operationTime;
this.totalFuelConsumption = fuelConsumption;
this.gpsLocation = location;
machineModelName = machine.getModelName();
machineName = machine.getName();
machineIconId = machine.getIconId();
machinePort = machine.getPort();
}
public String getDriver()
{
return driverName;
}
public int getCurrentTaskId()
{
return currentTaskId;
}
public long getIdleTime()
{
return idleTime;
}
public long getFullTime()
{
return fullTime;
}
public long getOperationTime()
{
return operationTime;
}
public double getTotalFuelConsumption()
{
return totalFuelConsumption;
}
public double getLocation()
{
return gpsLocation.getLatitude();
}
public String getMachineModelName()
{
return machineModelName;
}
public String getMachineName()
{
return machineName;
}
public int getMachineIconId()
{
return machineIconId;
}
public int getMachinePort()
{
return machinePort;
}
}
I tried to get the packet size from the size of the serialized packet or inserting arbitrary 2048 based on some examples on internet. Couldn't get it work though.
As far as i know the receive function returns the length of the bytes it received. But your buffer will be full:
Example:
int buffersize = 1024;
You send 8bytes over udp.
So your byte[] will be full with your 8 bytes but the rest of the 1024 will be 0.
save the size you get by the .receive() call and just save all values of your buffer to another byte[] and you should get your object.
For your example:
public ManagerUdpPacket receive()
{
int receivedBytes = 0;
//receive a packet
DatagramPacket recvPacket = new DatagramPacket(receiveData, receiveData.length);
try{
receivedBytes = clientSocket.receive(recvPacket);
}catch(IOException e){
Log.e("ERR", "IOException in UdpReceiver.receive");
return null;
}
byte[] myObject = new byte[receivedBytes];
for(int i = 0; i < receivedBytes; i++)
{
myObject[i] = receiveData[i];
}
ManagerUdpPacket obj = deserializeManagerPacket(myObject);
if (obj != null)
Log.v("udpPacket", "UDP saatu: " + obj.getDriver());
return obj;
}
When receiving data on UDP, always use java.net.DatagramSocket.getReceiveBufferSize();. This is the actual size of the platform or SP_RCVBUF for the socket. Since UDP is a datagram based protocol unlike TCP, which is streaming protocol, receiving buffers become critical for data sanity. Usually, receiving and sending buffers are equal in size, but you are not bothered while sending when using DatagramSocket.send(DatagramPacket), alternately, you can also use DatagramSocket.setSendBufferSize(DatagramSocket.getSendBufferSize()) for using the SO_SNDBUF option for this socket. Keep in mind, in UDP, if you use a SO_SNDBUF size greater than platform's, the packet can be discarded.