I'm trying to get a simple TCP client going that can
connect to the Dart VM service, send a request and get a response.
I've tried it with and without connect().
The other question I have is what's the best Dart command
to "start" the VM service so that it's listening for requests?
With possibly giving what host and port to use, if needed.
Commands like --observe or --enable-vm-service are for the Observatory and I don't need that.
I've been using this
but I'm not sure what host and port it's using by default for that.
dart --pause_isolates_on_start bicycle.dart
So far, after I run the Dart command and run the client,
I get:
Exception: java.net.ConnectException: Connection refused: connect
or it seems to send the request, but it just gets back "-1".
So what Dart command should I be using and what changes do I need to
make to be able to get a response back from the VM service?
I need to be able to do the client in Java and not Dart.
UPDATE:
Is the problem that the Dart VM service is using WebSockets and that
isn't compatible with Java Socket I/O?
It's looking like it does need to connect via a WebSocket, so I'm
looking into trying to get that to build and try it.
Thanks!!
import java.net.Socket;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketAddress;
import java.net.InetAddress;
import java.net.InetSocketAddress;
public class DartTest
{
public static void main(String[] args)
{
Socket socket = null;
InetAddress inetAddress = null;
InetSocketAddress inetSocketAddress = null;
OutputStream os = null;
InputStream is = null;
byte[] outBuf;
byte[] inBuf;
byte[] zeroDzeroAspaces = {(byte)0x0d, (byte)0x0a, (byte)0x20, (byte)0x20};
String sZeroDzeroAspaces = new String(zeroDzeroAspaces);
byte[] zeroDzeroA = {(byte)0x0d, (byte)0x0a};
String sZeroDzeroA = new String(zeroDzeroA);
int iAvail;
int iByte;
int iReadBytes;
StringBuffer readSb = new StringBuffer();
String sHost = "127.0.0.1";
int iPort = 8181;
try
{
//inetSocketAddress = new InetSocketAddress(sHost, iPort);
socket = new Socket(sHost, iPort);
//socket = new Socket();
//socket.connect((SocketAddress)inetSocketAddress);
os = socket.getOutputStream();
is = socket.getInputStream();
StringBuffer outSb = new StringBuffer();
outSb.append("{");
outSb.append(sZeroDzeroAspaces);
outSb.append((char)0x22);
outSb.append("jsonrpc");
outSb.append((char)0x22);
outSb.append(": ");
outSb.append((char)0x22);
outSb.append("2.0");
outSb.append((char)0x22);
outSb.append(",");
outSb.append(sZeroDzeroAspaces);
outSb.append((char)0x22);
outSb.append("method");
outSb.append((char)0x22);
outSb.append(": ");
outSb.append((char)0x22);
outSb.append("getVersion");
outSb.append((char)0x22);
outSb.append(",");
outSb.append(sZeroDzeroAspaces);
outSb.append((char)0x22);
outSb.append("params");
outSb.append((char)0x22);
outSb.append(": {},");
outSb.append(sZeroDzeroAspaces);
outSb.append((char)0x22);
outSb.append("id");
outSb.append((char)0x22);
outSb.append(": ");
outSb.append((char)0x22);
outSb.append("1");
outSb.append((char)0x22);
outSb.append(sZeroDzeroA);
outSb.append("}");
//System.out.println("outSb: '"+outSb.toString()+"'");
outBuf = outSb.toString().getBytes();
os.write(outBuf);
os.flush();
while ( true )
{
iByte = is.read();
System.out.println("iByte: "+iByte);
if ( iByte == -1 )
break;
readSb.append((char)iByte);
}
System.out.println("readSb: '"+readSb.toString()+"'");
if ( socket != null )
socket.close();
}
catch (Exception e)
{
System.out.println("Exception: "+e.toString());
}
}
}
Answering my own question:
Using WebSockets was the main thing, trying to connect to
the VM service/Observatory using "regular" Socket TCP
wasn't going to work.
Then the next roadblock came when the WebSocket server handshake
was failing when it would return "200 OK" instead of "101" to "Upgrade".
Then I was looking at the intelliJ plugin code, to see how they connected, and they used "ws://localhost:8181/ws", I was trying to use
"ws://localhost:8181", and once I used that, the handshake went through!!
When it worked I was using:
dart --enable-vm-service --pause_isolates_on_start bicycle.dart
I'm not sure who I'm actually connected to, the Observatory,
or the VM service, but at least I've finally gotten to the point
where I can try to send a request, and possibly get a reply.
Related
I am trying to combine Python and Java using a socket connection. I hava a Java server and a Python client. They are able to connect to each other, and the server is able to write to the client, but when I try to send a message from the client to the server, it throws an EOFException. What should I do to get this to work?
Server code:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) {
try {
ServerSocket serversocket = new ServerSocket(6000);
Socket client = serversocket.accept();
final DataInputStream input = new DataInputStream(client.getInputStream());
final DataOutputStream output = new DataOutputStream(client.getOutputStream());
output.writeUTF("Hello Client!");
String message = (String)input.readUTF();
System.out.println(message);
serversocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Client code:
import socket
socket = socket.socket()
host = "localhost"
port = 6000
socket.connect((host, port))
message = socket.recv(1024)
print(message.decode())
socket.sendall("Hello Server".encode())
socket.close()
The exception:
java.io.EOFException
at java.base/java.io.DataInputStream.readFully(DataInputStream.java:203)
at java.base/java.io.DataInputStream.readUTF(DataInputStream.java:615)
at java.base/java.io.DataInputStream.readUTF(DataInputStream.java:570)
at Server.main(Server.java:19)
Option #1:
Replace input.readUTF() in server with this:
while(true) {
int ch = input.read();
if (ch == -1) break;
System.out.print((char)ch);
}
Option #2:
If want to read UTF-encoded strings (vs plain ASCII) on server then recommend using BufferedReader with utf-8 charset and readLine().
ServerSocket serversocket = new ServerSocket(6000);
System.out.println("Waiting for connections");
Socket client = serversocket.accept();
final BufferedReader input = new BufferedReader(
new InputStreamReader(client.getInputStream(), StandardCharsets.UTF_8)); // changed
final OutputStream output = client.getOutputStream();
//output.writeUTF("Hello Client!"); // see note below
output.write("Hello Client!".getBytes(StandardCharsets.UTF_8)) // changed
String message = input.readLine(); // changed
System.out.println(message);
client.close();
serversocket.close();
Client output:
Hello Client!
Server output:
Hello Server
Note JavaDoc of DataOutputStream#writeUTF(...) says:
First, two bytes are written to the output stream as if by the
writeShort method giving the number of bytes to follow.
Using output.write(s.getBytes(StandardCharsets.UTF_8)) is more compatible with non-Java clients. Python utf-8 decoding doesn't support the 2-byte length prefix added by writeUTF().
Finally, if want the server to handle more than one client connection, then add a loop that encloses the code after ServerSocket is created and only close the client socket inside the loop.
I am trying to exchange some string data between a Python Server (ideally, a Raspberry Pi with some device connected through GPIO) and a Java Client (again, the main target would be an Android app). The following code, anyway, is running on a standard local PC.
This is the code for the server, taken (and slightly modified) from here:
import socketserver
import datetime
class MyTCPHandler(socketserver.StreamRequestHandler):
def handle(self):
now = datetime.datetime.now()
answer = now
self.data = self.rfile.readline().strip()
print("Read!")
if str(self.data) == 'date':
answer = now.date()
elif str(self.data) == 'time':
answer = now.time()
self.wfile.write((str(answer)+"\n").encode('utf-8'))
print("Sent!")
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
with socketserver.TCPServer((HOST, PORT), MyTCPHandler) as server:
print("Server is running on {}, port {}".format(HOST, PORT))
server.serve_forever()
The Java client is the following:
public class SocketTest {
public static void main(String[] args) {
try {
Socket s = new Socket("127.0.0.1", 9999);
PrintWriter out = new PrintWriter(new OutputStreamWriter(s.getOutputStream()));
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
out.println("date".getBytes());
String resp = in.readLine();
System.out.println("Received: " + resp);
} catch (IOException ex) {
Logger.getLogger(SocketTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
No exception is thrown whatsoever, it just gets stuck waiting for the response on the client side, and I can never see the "Read!" message on the server side.
The "date".getBytes() comes from somewhere on the net where I found that the Python sockets expect bytes (UTF-8), but in Java I'm sending strings directly, so it might be wrong.
Any help will be appreciated!
Turnes out, it was a flushing problem.
Apparently, the buffer is not flushed when the end of line is reached (which is how I was expecting it to behave).
Adding a simple out.flush() solved the problem.
I am having trouble with using sockets
As you can see the codes worked when I tried to send string from JAVA to PYTHON.
But however I am having trouble when I tried to send string from PYTHON to JAVA ,which is the opposite way. And I need it to convert into bytes and decode it since I encoded the string before I send it over.
Thus the problem now is how or is there anything wrong in my codes when I send a string from Python socket and receiving the string by Java Socket?
I really need help, thank you!
Python (SERVER) Codes:
import socket
import ssl
import hashlib
import os
from Crypto.Cipher import AES
import hashlib
from Crypto import Random
sHost = ''
sPort = 1234
def bindSocket():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #IPv4 and TCP
try:
s.bind((sHost,sPort))
print("Socket created and binded")
except socket.error as msgError:
print(msgError)
print("Error in Binding Socket")
return s #so that we can use it
def socketConnect():
s.listen(1) #listen to 1 connection at a time
while True:
try:
conn, address = s.accept() #Accept connection from client
print ("Connected to: " + address[0] + ":" +str(address[1]))
except socket.error as error:
print ("Error: {0}" .format(e))
print ("Unable to start socket")
return conn
def loopCommand(conn):
while True:
passphrase = "Hello Java Client "
data = conn.recv(1024)#receive the message sent by client
print(data)
conn.send(passphrase.encode('utf-8'))
print("Another String is sent to Java")
s = bindSocket()
while True:
try:
conn = socketConnect()
loopCommand(conn)
except:
pass
Java (Client) Codes:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class SocketSTesting {
public Socket socketStartConnect() throws UnknownHostException, IOException {
String ip = "192.168.1.16";
int port = 1234;
Socket clientSocket = new Socket(ip, port);
if (clientSocket.isConnected()) {
System.out.println("It is connected to the server which is " + clientSocket.getInetAddress());
} else if (clientSocket.isClosed()) {
System.out.println("Connection Failed");
}
return clientSocket;
}
public void sendString(String str) throws Exception {
// Get the socket's output stream
Socket socket = socketStartConnect();
OutputStream socketOutput = socket.getOutputStream();
byte[] strBytes = str.getBytes();
// total byte
byte[] totalByteCombine = new byte[strBytes.length];
System.arraycopy(strBytes, 0, totalByteCombine, 0, strBytes.length);
//Send to Python Server
socketOutput.write(totalByteCombine, 0, totalByteCombine.length);
System.out.println("Content sent successfully");
//Receieve Python string
InputStream socketInput = socket.getInputStream();
String messagetype = socketOutput.toString();
System.out.println(messagetype);
}
public static void main(String[] args) throws Exception {
SocketSTesting client = new SocketSTesting();
String str = "Hello Python Server!";
client.sendString(str);
}
}
You seem to think that String messagetype = socketOutput.toString(); performs I/O. It doesn't, so printing it or even calling it does nothing and proves nothing. You need to read from the socket input stream.
BTW clientSocket.isConnected() cannot possibly be false at the point you are testing it. If the connect had failed, an exception would have been thrown. Similarly, clientSocket.isClosed() cannot possibly be true at the point you are testing it, because you haven't closed the socket you just created. Further, if isClosed() was true it would not mean 'connection failed', and isConnected() being false does not entail isClosed() being true. Remove all this.
This is not a possible duplicate. No answer on this site adequately answers or solves my issue.
I am trying to connect to a VB.NET server via TCP socket and get response in Android application. The response is always null as string or -1 as bytes.
I have to connect and get a response for multiple platforms but for the moment I just want to focus on the Android app. Maybe if I figure it out, it will be easier to move forward to other platforms.
I do not have access to edit any code in the VB.NET live server. There system is pretty old and has been only sending responses to other Windows clients up until now.
Here is my Android client. It is inside a background task which is called from the mainActivity. The below command string should return coordinates in the form of a string from the server. Nothing is returned.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void sendMessage() throws IOException, InterruptedException {
Socket socket = null;
String host = "";
int port = ;
PrintStream stream = null;
String command="";
try {
Socket s = new Socket(host,port);
System.out.println("Socket created");
//outgoing stream redirect to socket
OutputStream out = s.getOutputStream();
PrintWriter output = new PrintWriter(out);
output.println(command);
output.flush();
System.out.println("command sent");
BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
//read line(s)
System.out.println("Getting response:");
String st = input.readLine();
System.out.println("Response : " + st);
//Close connection
s.close();
}
catch (UnknownHostException e) {
System.out.println("Don't know about host : " + host);
e.printStackTrace();
System.exit(1);
}
catch (IOException e) {
System.out.println("Couldn't get I/O for the connection to : " + host);
e.printStackTrace();
System.exit(1);
}
}
}
A developer also sent me a test client in VB which connects, sends and recieves without problem
Here is a class of a VB:NET Dummy server project the developer has sent me to see how the live server is setup code-wise. I can see it gets the string as unicode but I am not confident in VB to know where my Java code is going wrong.
When I open the project and start the server on localhost I cant connect to it from the java client anyway. Then I have written another client in PHP, same problem, connection established but no response. I downloaded a socket tester software but it also can connect but does not get a response.
Option Explicit On
Imports System
Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports Microsoft.VisualBasic
Imports System.Net.Dns
Imports System.Text.UnicodeEncoding
Imports System.Threading
Imports System.Data.SqlClient
Public Enum glenConnectionType
ConstantConnection = 1
ConnectOnDemand = 2
AsyncConnection = 3
End Enum
Public Class clsDynaListner
Public tcpServer As Socket
Public tcpClient As Socket
Public tcpPort As Integer
Public tcpBilnr As Integer ' was shared SHOULD PROB BE INITIALISED TO 0
Public ThreadClient As Thread
Public LastKontakt As Date = Nothing
Public ConActive As Boolean = False
Private tcpClientEndPoint As System.Net.IPEndPoint
Private bCommandLength(15), bReplyLength(15) As Byte
Private iCommandLength, iReplyLength As Integer
Private sReplyLength As String
Private sCommand, sReply As String
Private theCommandBytes() As Byte
Private theReplyBytes() As Byte
Private Const AsyncMaxBytes As Integer = 600000 '1024
Public Shared AsyncData As String = Nothing
Public Sub New(ByVal currentTCPPort As Integer, ByVal theConnectionType As glenConnectionType)
tcpPort = currentTCPPort
tcpClientEndPoint = New System.Net.IPEndPoint(System.Net.IPAddress.Any, tcpPort)
'Select Case theConnectionType
' Case glenConnectionType.ConstantConnection
' ThreadClient = New Threading.Thread(AddressOf ListenForConstantConnection)
' Case glenConnectionType.ConnectOnDemand
ThreadClient = New Threading.Thread(AddressOf ListenForConnectOnDemand)
' Case glenConnectionType.AsyncConnection
'ThreadClient = New Threading.Thread(AddressOf ListenForAsyncConnection)
'End Select
ThreadClient.Start()
End Sub
Private Sub ListenForConnectOnDemand()
While (True)
Try
tcpServer = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
tcpServer.SendBufferSize = TCP_BUFFER_SIZE
tcpServer.ReceiveBufferSize = TCP_BUFFER_SIZE
tcpServer.Blocking = True
tcpServer.Bind(tcpClientEndPoint)
tcpServer.Listen(0)
tcpClient = tcpServer.Accept
tcpClient.SendBufferSize = TCP_BUFFER_SIZE
tcpClient.ReceiveBufferSize = TCP_BUFFER_SIZE
' Find out how big the command is going to be
tcpClient.Receive(bCommandLength)
iCommandLength = CType(Unicode.GetString(bCommandLength), Integer)
' Bring that command to daddy
Array.Resize(theCommandBytes, iCommandLength + 1)
tcpClient.Receive(theCommandBytes)
sCommand = Unicode.GetString(theCommandBytes)
gInMessage = sCommand
' Get the reply
sReply = "Response:"
gOutMessage = sReply
' Inform the controller of the length of the reply transmission
iReplyLength = (sReply.Length * 2) - 1
sReplyLength = iReplyLength.ToString.PadLeft(8, "0")
bReplyLength = Unicode.GetBytes(sReplyLength)
tcpClient.Send(bReplyLength)
' Send the reply data
Array.Resize(theReplyBytes, iReplyLength + 1)
theReplyBytes = Unicode.GetBytes(sReply)
tcpClient.Send(theReplyBytes)
Array.Clear(theCommandBytes, 0, theCommandBytes.Length)
Array.Clear(theReplyBytes, 0, theReplyBytes.Length)
tcpClient.Close()
tcpServer.Close()
tcpClient = Nothing
tcpServer = Nothing
Catch ex1 As Exception
Try
tcpClient.Close()
tcpServer.Close()
tcpClient = Nothing
tcpServer = Nothing
' ErrMessage = "LisForContr :" & tcpPort.ToString & ex1.Message
Catch
End Try
End Try
End While
End Sub
Protected Overrides Sub Finalize()
Try
tcpServer.Close()
ThreadClient.Abort()
Catch
End Try
MyBase.Finalize()
End Sub
End Class
I have been working with this for a while. The apps I have built are complete for PHP Web App, Android Native, and iPhone Native. The problem is only getting the response from the VB server.
Would like some help to push me in the right direction.
Also I enquired with the developers if the response has a line-break. It does not and it does seem they are willing to mess with the code as it served there purpose for many many years. So I have to find away around that.
If you need me to provide more info just ask.
To send to a VB.NET server from Java you must send the string as unicoded bytes. Send the length at the bytes to expect first and then send the primary data and flush. You have to know exactly what the server is expecting in order to format and encode the data accordingly in preparation to send it.
I was able to successfully fix my issue after debugging VB client and server. This client will process byte arrays, stream advanced sql commands and get the response. The update will be getting xml table data. Anyone who wants to input how to make this client better. You are welcome.
Updated my java client as follows.
/**
* MR-TCP Java & VB.NET DataExchange Client 0.95 - Maze Runner 2015
*/
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
public class Client {
public static String sendCommand(String commandString, Boolean IsID) throws IOException, InterruptedException {
String host;
int port;
String command;
byte[] commandBytes;
String commandLength;
byte[] cmdLengthBytes;
Socket s;
DataOutputStream stream;
String dataString = "";
host = ""; //
port = 0; //
command = commandString;
commandBytes = command.getBytes("UTF-16LE"); // returns byte[18]
if(IsID){
commandLength = "00000021";
cmdLengthBytes = commandLength.getBytes("UTF-16LE");
} else {
String iCommandLength = command; // Get the command length
cmdLengthBytes = iCommandLength.getBytes("UTF-16LE");
int commandNewLength = cmdLengthBytes.length-1;
String newLength = "0000" + String.valueOf(commandNewLength);
cmdLengthBytes = newLength.getBytes("UTF-16LE");
}
try {
s = new Socket(host, port); // Connect to server
//Send the command to the server
stream = new DataOutputStream(s.getOutputStream()); // get ready to send
stream.write(cmdLengthBytes); // tell the server how many bytes to expect
System.out.println("Command length sent");
stream.write(commandBytes); // Send the command to papa...
stream.flush(); // guaranteed sending
System.out.println("Command sent");
//Receive the command from the server.
DataInputStream is = new DataInputStream(s.getInputStream()); // get ready to receive
ByteArrayOutputStream buffer = new ByteArrayOutputStream(); // prepare to get array
int nRead;
byte[] data = new byte[1024];
while ((nRead = is.read(data, 0, data.length)) != -1) { // read the array byte by byte
buffer.write(data, 0, nRead);
}
byte[] dataBytes = buffer.toByteArray(); // get complete array
dataString = buffer.toString("UTF-16LE").substring(8); // get rid of the array length and convert to string
stream.close(); // close the dataStream
s.close(); // close the connection
System.out.println("Disconnected");
} catch (IOException e){
e.printStackTrace();
}
System.out.println("Function Complete");
System.out.println("Server response:" + dataString);
return dataString;
}
}
I have a local network with DHCP and a few PCs. One of these should be my Server and get automatically connected to all others (clients). My idea was this:
First, I create a server on every client (CServer) that is listening for a client programm from the server (SClient). When the SClient connects to a CServer, the SClient sends the CServer his IP, so he knows there will be the server on this IP. Then after trying all IPs in his IP range (e.g. 192.168.1.xxx), he starts the real server and all the clients connect to the known server IP.
But when I try the following, the SClient just freezes at the first IP, when trying to connect to 192.168.1.0. How can i define a timeout or something similar that lets the SClient drop the unsuccessful connection and going on with 192.168.1.1?
import java.lang.*;
import java.io.*;
import java.net.*;
class SClient {
public SClient() {
for(int i = 120; i < 125; i++){
try{
InetAddress addr = InetAddress.getLocalHost();
String addrs = addr+"";
String ip = addrs.substring(addrs.indexOf("/")+1);
Socket s1 = new Socket("192.168.1." + i, 1254);
OutputStream s1out = s1.getOutputStream();
DataOutputStream dos = new DataOutputStream (s1out);
dos.writeUTF(ip);
dos.close();
s1out.close();
s1.close();
}catch(IOException e){}
}
}
}
and
import java.lang.*;
import java.io.*;
import java.net.*;
class CServer {
public CServer() throws IOException{
ServerSocket s = new ServerSocket(1254);
while(true){
Socket s1=s.accept();
InputStream s1In = s1.getInputStream();
DataInputStream dis = new DataInputStream(s1In);
String st = new String (dis.readUTF());
System.out.println(st);
dis.close();
s1In.close();
s1.close();
}
}
}
I've found a solution for my problem. It was just initializing the Socket not with
Socket s1 = new Socket("192.168.1." + i, 1254);
but with
Socket s1 = new Socket();
s1.setSoTimeout(200);
s1.connect(new InetSocketAddress("192.168.1." + i, 1254), 200);
Thanks anyway!
It's much easier to do this with UDP. The general logic would be:
Identify a well known port for 'discovery'
Any machine that starts up sends out a 'Query Master Server' message
If a response is not received to that message within a time frame
you define, then the machine that sent it automatically designates
itself as being the server.
Henceforth, any machine that sends out a 'Query Master Server'
message will get a response back from the master, with its IP
address and a 'communication port'
Connect from the new machine to the server on the communication port
and start sending messages.
You might run into situations where more than one server thinks it is the master in this scenario, and then you would need a conflict resolution process, but the outline should give you a general idea of a process that will work for you.