How can I send string data from Java to a C++ console application under Windows? I am trying to do this:
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
String o = ...;
proc.getOutputStream().write(o.getBytes());
But I never see it on the C++ side when I do this:
ReadFile(stdin_h,buf, sizeof(buf), &bytes, 0)
ReadFile never returns.
What follows is further elaboration and sample code.
I have written a simple C++ console (Win32) application which reads from STDIN and performs actions based on input.
Now I want to write a Java application to "drive" the C++ application. The Java applicaton should:
Start the C++ application using Runtime.exec()
Write string data to the C++ app's STDIN
Repeat until it's time to die.
My Java application seems to be working, but the C++ application never receives any data on STDIN.
Here is the C++ application:
int main()
{
ofstream f("c:\\temp\\hacks.txt");
HANDLE stdin_h = GetStdHandle(STD_INPUT_HANDLE);
DWORD file_type = GetFileType(stdin_h);
if( file_type != FILE_TYPE_CHAR )
return 42;
f << "Pipe" << endl;
for( bool cont = true; cont; )
{
char buf[64*1024] = {};
DWORD bytes = 0;
if( ReadFile(stdin_h,buf, sizeof(buf), &bytes, 0) )
{
string in(buf,bytes);
cout << "Got " << in.length() << " bytes: '" << in << "'" << endl;
f << "Got " << in.length() << " bytes: '" << in << "'" << endl;
if( in.find('Q') )
cont = false;
}
else
{
cout << "Err " << GetLastError() << " while reading file" << endl;
f << "Err " << GetLastError() << " while reading file" << endl;
}
}
}
And here is the Java side:
public static void main(String[] args) {
Runtime rt =Runtime.getRuntime();
try {
Process proc = rt.exec("c:\\dev\\hacks\\x64\\debug\\hacks.exe");
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
int a = 0;
while(a < 5)
{
String o = (a == 4 ? "Q\n" : "A\n");
proc.getOutputStream().write(o.getBytes());
System.out.println("Wrote '" + o + "'");
++a;
}
try {
proc.waitFor();
// TODO code application logic here
} catch (InterruptedException ex) {
Logger.getLogger(Java_hacks.class.getName()).log(Level.SEVERE, null, ex);
}
} catch (IOException ex) {
Logger.getLogger(Java_hacks.class.getName()).log(Level.SEVERE, null, ex);
}
}
The Java side seems to be working correctly, but I'm not ever receiving the strings on the C++ side.
Am I doing something wrong here? How can I send string data from Java to a C++ console application under Windows?
Why are you not flushing the output stream on the Java side after writing 5 strings?
proc.getOutputStream().flush();
Related
I am trying to connect to WebSocket (currently using the chrome extension). I got it working that I receive the data. When I try to convert the integers I receive from the input stream I get totally other values. In the example below I gave in the word test as input. So do I do something wrong or do I interpret the input wrong?
Code:
#Override
public void run() {
while (true) {
try {
if(client.getInputStream().read() != -1) {
int i = client.getInputStream().read();
System.out.println("Integer: " + i);
byte b = (byte) i;
System.out.println("Byte: " + b);
char c = (char) b;
System.out.println("Char: " + c);
System.out.println("-=-=-=-=-=-=-=-=-=-=-=-");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Output:
output
A java stream returns bytes, but read returns an int so that you can get -1. So if your server is sending an int, then you need to read all of the bytes for that int and create it.
You have two ways to do this. Create a byte[] and use it as a buffer or if you're receiving 32 bit twos complement integers then you can use a DataInputStream.
An example using a buffer.
#Override
public void run() {
while (true) {
try {
byte[] buffer = new byte[4];
if(client.getInputStream().read(buffer) != -1) {
int i = (
( ( buffer[0] & 0xff ) << 24 ) |
( ( buffer[1] & 0xff ) << 16 ) |
( (buffer[2] & 0xff ) << 8) |
(buffer[3] & 0xff)
);
System.out.println("Integer: " + i);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Or you can use a DataInputStream.
DataInputStream dis = new DataInputStream(client.getInputStream());
try{
int i = dis.readInt();
} catch( EOFException e){
//end of file. This is like getting -1.
} catch( IOException e ){
//do something for an error
}
The buffer version uses the same conversion as java's DataInput.readInt, I've included it for an example. Also there is some additional checking that should be done. Even though the buffer is 4 bytes long, you could read anything from 1 to 4 bytes.
I'm sending a file from Server (Java) to client (C++).
While everywhere else the data is recevied just fine. In this area, Sometimes there is "MZ[]" appended to the filename.
Here is the Receving code (C++):
else if(command == "freceive")
{
// Receive Filename
int fsize, l = 0;
WIN32_FIND_DATA FindFileData;
HANDLE hFind;
char filetoSave[BUFFER] = { 0 };
std::ostringstream response;
memset(filetoSave, '\0', BUFFER);
int fl = recv(sockfd, filetoSave, BUFFER, 0);
if (fl == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET)
{
connected = false;
}
//===================================================
std::ofstream File(filetoSave, std::ios::app | std::ios::binary);
memset(recvbuf, '\0', BUFFER);
// Recevie File
while ((fsize = recv(sockfd, recvbuf + l, sizeof(recvbuf) - l, 0)) > 0)
{
if(fsize > 0){
File.write(recvbuf, fsize);
}
}
File.close();
if(fsize == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET)
{
connected = false;
}
File.close();
if(IsFile((char*)filetoSave) == TRUE){
hFind = FindFirstFile(filetoSave , &FindFileData);
if (hFind == INVALID_HANDLE_VALUE)
{
response << "ERROR Receiving file (" << filetoSave << ") : " << GetLastError();
}
else
{
ULONGLONG FileSize = FindFileData.nFileSizeHigh;
FileSize <<= sizeof( FindFileData.nFileSizeHigh ) * 8;
FileSize |= FindFileData.nFileSizeLow;
response << "Saved : '" << filetoSave << "'\nSize : " << FileSize << " bytes.\nSaved as : " << filetoSave;
FindClose(hFind);
}
} else {
response << "Error File not found (" << filetoSave << ") : " << GetLastError();
}
EncSend(response.str().c_str());
}
and here is the part of the server which sends the filename (Java):
public static void SendRaw(Socket sock, String data)
{
try {
OutputStream outputStream = sock.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
dataOutputStream.write(data.getBytes());
dataOutputStream.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NullPointerException ne) {
ne.printStackTrace();
}
}
Everything is going ok except the fact that the filename has MZ[] appended to it which I do not want.
Why is this happening? It has given me a headache! Where is this MZ[] coming from!?
Here's a screenshot, Note after MZ there is a wierd ascii char like [] in absolute filename, But os ignores it.
screenshot here
Hey guys, here is my code.
int main() {
char buffer[BUFSIZE];
// define our address structure, stores our port
// and our ip address, and the socket type, etc..
struct sockaddr_in addrinfo;
addrinfo.sin_family = AF_INET;
addrinfo.sin_port = htons(PORT);
addrinfo.sin_addr.s_addr = INADDR_ANY;
// create our socket.
int sock;
if ( (sock = socket(addrinfo.sin_family, SOCK_STREAM, 0)) < 0) {
cout << "Error in creating the socket.";
}
// bind our socket to the actual adress we want
if (bind(sock, (struct sockaddr*)&addrinfo, sizeof(addrinfo)) != 0) {
cout << "Error in binding.";
}
// open the socket up for listening
if (listen(sock, 5) != 0) {
cout << "Error in opening listener.";
}
cout << "Waiting for connections...." << endl;
char *msg = "Success! You are connected.\r\n";
// continuously accept new connections.. but no multithreading.. yet
while(1) {
struct sockaddr_in client_addr;
socklen_t sin_size = sizeof(client_addr);
if(int client = accept(sock, (struct sockaddr*)&client_addr, &sin_size)) {
cout << "Recived new connection from " << inet_ntoa(client_addr.sin_addr) << endl;
send(client, msg, strlen(msg), 0);
while(1) {
send(client, buffer, recv(client, buffer, BUFSIZE, 0), 0);
cout << buffer << endl;
strcpy(buffer, "");
}
} else {
cout << "Error in accepting new connection." << endl;
}
}
close(sock);
return 0;
}
Now, I'm very new to sockets, Im just sort of trying to get a feel for them but I do have some experience with sockets in PHP. I'm using telnet via putty on my linux machine to test this, I don't know if thats causing any issues but the server is outputting some strange characters and I don't know why. I think it has something to do with the buffer, but I'm not really sure. I can send things like "hi" to the server via telnet and it outputs them just fine and sends them back to me but when I send things like "hoobla" it starts the funky character stuff. Any suggestions would be helpful!
Thanks in advance!
You're getting rubbish printed out because recv does not null-terminate your buffer.
The important section in the below code is:
int num = recv(client,buffer,BUFSIZE,0);
if (num < 1) break;
send(client, ">> ", 3, 0); // <<-- Nice to have.
send(client, buffer, num, 0);
buffer[num] = '\0'; // <<-- Really important bit!
if (buffer[num-1] == '\n') // <<-- Nice to have.
buffer[num-1] = '\0'; // <<-- Nice to have.
cout << buffer << endl;
which will properly terminate your buffer before trying to print it, as well as remove the trailing newline if present (and allow the client to distinguish between input and echoed lines).
This one (a complete program) works a little better:
using namespace std;
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#define BUFSIZE 1000
#define PORT 1234
int main() {
char buffer[BUFSIZE];
// define our address structure, stores our port
// and our ip address, and the socket type, etc..
struct sockaddr_in addrinfo;
addrinfo.sin_family = AF_INET;
addrinfo.sin_port = htons(PORT);
addrinfo.sin_addr.s_addr = INADDR_ANY;
// create our socket.
int sock;
if ( (sock = socket(addrinfo.sin_family, SOCK_STREAM, 0)) < 0) {
cout << "Error in creating the socket.";
return -1;
}
// bind our socket to the actual adress we want
if (bind(sock, (struct sockaddr*)&addrinfo, sizeof(addrinfo)) != 0) {
cout << "Error in binding.";
return -1;
}
// open the socket up for listening
if (listen(sock, 5) != 0) {
cout << "Error in opening listener.";
return -1;
}
char *msg = "Success! You are connected.\r\n";
// continuously accept new connections.. but no multithreading.. yet
while(1) {
cout << "Waiting for connections...." << endl;
struct sockaddr_in client_addr;
socklen_t sin_size = sizeof(client_addr);
if(int client =
accept(sock, (struct sockaddr*)&client_addr, &sin_size))
{
cout << "Recieved new connection from "
<< inet_ntoa(client_addr.sin_addr) << endl;
send(client, msg, strlen(msg), 0);
while(1) {
int num = recv(client,buffer,BUFSIZE,0);
if (num < 1) break;
send(client, ">> ", 3, 0);
send(client, buffer, num, 0);
buffer[num] = '\0';
if (buffer[num-1] == '\n')
buffer[num-1] = '\0';
cout << buffer << endl;
strcpy(buffer, "");
}
} else {
cout << "Error in accepting new connection." << endl;
}
}
close(sock);
return 0;
}
On the client side:
$ telnet 127.0.0.1 1234
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Success! You are connected.
hello
>> hello
my name is pax
>> my name is pax
and you?
>> and you?
<CTRL-D>
Connection closed by foreign host.
and, on the server side:
$ ./testprog
Waiting for connections....
Recived new connection from 127.0.0.1
hello
my name is pax
and you?
Waiting for connections....
The problem is that buffer is not guaranteed to contain a string-terminating null character. Add the line buffer[BUFSIZE-1] = '\0' just before your cout << buffer.
Even better, actually record how many bytes were received, and use that information to determine if you overran your buffer.
EDIT: I've managed to connect the server from a python client, which means that there's a problem in the ANDROID connection. I've been trying to figure it out in the last 2 hours- the connect() function nor the socket() function, does nothing! I'm freaking out.
PROBLEM: ,
I'm working on an android application, which basically communicates with a server that runs on my laptop in c++ (my laptop OS is Windows 8).
My client connects to the server only when I'm connected to my home network. When I'm connected to other networks, my client throws an exception:
** The server computer connected with a cable **
java.net.SocketTimeoutException: failed to connect to /192.168.43.60 (port 5898) after 3000ms
The Android code:
Thread th = new Thread(new Runnable() {
public void run() {
Socket client_socket = new Socket(); // Creates a socket and binds it to available port.
Log.d("INFO", "Created Socket");
for (int retries = 0; retries < 3; retries++) {
try {
client_socket.connect(new InetSocketAddress("127.0.0.1", 5898), 3000); // Connect to the server.
break;
} catch (java.net.SocketTimeoutException e) {
Log.d("INFO", "Connect() failed with an error.");
e.printStackTrace();
continue;
}
}
}
Log.d("INFO", "Connecting to server on " + ProtCodes.serverIP + ":" + ProtCodes.serverPORT);
};
th.start();
th.join();
Server side:
using namespace std;
int main(int argc, char* argv[])
{
Server* server;
SOCKADDR_IN sockAddrIn;
CLIENT_INFO client_info;
int iResult = 0, number_of_connected_clients = 0, clientLen = sizeof(sockAddrIn);
std::list<SOCKADDR_IN>* connected_clients; //list of connected clients SOCKADDRS structs (for ip & port)
t1 = clock();
try { //validates the PORT argument
if (atoi(argv[0]) > 1024 && atoi(argv[0]) < 65535)
server = new Server(atoi(argv[0]));
else
server = new Server(DEFAULT_PORT);
}catch (...){
server = new Server(5898);
}
iResult = listen(server->getSocket(), SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
closesocket(server->getSocket());
WSACleanup();
return TRUE;
}
cout << endl << "#Server_log: Connected!" << endl;
cout << "#Server_log: Launching MySQL server, version: " << string(mysql_get_client_info()) << endl;
cout << "#Server_log: Server is up running on " << get_ipv4_address() << ":" << ntohs(server->get_server_info().sin_port) << endl;
cout << "#Server_log: Waiting for requests..." << endl;
cout << "*******************************************" << endl << endl;
std::thread server_command(&handle_server_commands, server); //thread for server commands
server_command.detach();
/* Accept a client socket */
while (number_of_connected_clients < MAX_CONNECTIONS)
{
memset(&sockAddrIn, 0, sizeof(sockAddrIn));
clientLen = sizeof(sockAddrIn);
ClientSocket = accept(server->getSocket(), (struct sockaddrn*)&sockAddrIn, &clientLen);
if (ClientSocket == INVALID_SOCKET)
{
printf("accept failed with error: %d\n", WSAGetLastError());
continue;
}
/* Print connected client info */
client_info.ip = inet_ntoa(sockAddrIn.sin_addr);
client_info.port = ntohs(sockAddrIn.sin_port);
cout << endl;
get_current_time();
cout << "Client connected on " << client_info.ip << " : " << client_info.port << " !" << endl;
cout << endl << ">> ";
connected_clients = server->get_connected_clients();
connected_clients->push_back(sockAddrIn); //push client SOCKADDR struct into server's clients list
std::thread a(&(handle_user_requests), ClientSocket, server, client_info); //thread for clients requests handle
a.detach();
}
closesocket(ClientSocket);
closesocket(server->getSocket());
WSACleanup();
}
Thanks a lot!
Idan
I have to make an abstaction in my software - replace direct unblockable NIO sockets ( client/server ) to software abstraction.
For example, instead of connecting via tcp client would exec openssl s_client -connect xxx.xxx.xxx.xxx . I have written a little demo, and it even works. Sometimes :(
The first trouble is that Process's streams can't be used with Selector, so I can't replace socketchannel with any other type of channel, so I have to read/write without any chance to avoid blocking.
The second one is that a protocol is a duplex binary file-transfer protocol ( binkp ), so process's buffered streams are unusabe. I've tried to avoid that converting in/out data to base64 and it works, but also sometimes.
I can't understant why it works or not sometimes. I put a piece of test code below. The first word is frame's length, but first bit is ignored. Please, tell me your guesses. Thanks.
public class BufferedSocketBase64 {
static class InToOut implements Runnable {
InputStream is;
OutputStream os;
boolean direction; //
public InToOut(InputStream is, OutputStream os, boolean direction) {
super();
this.is = is;
this.os = os;
this.direction = direction;
}
#Override
public void run() {
System.out.println(Thread.currentThread().getId() + " start "
+ ((direction) ? "encode from to" : "decode from to"));
boolean eof = false;
while (true) {
if (direction) {
// encode to base64 data
try {
int[] head = new int[2];
for (int i = 0; i < 2; i++) {
head[i] = is.read();
}
int len = (head[0] & 0xff << 8 | head[1] & 0xff) & 0x7FFF;
byte[] buf = new byte[len + 2];
buf[0] = (byte) (head[0] & 0xff);
buf[1] = (byte) (head[1] & 0xff);
for (int i = 2; i < len; i++) {
buf[i] = (byte) (is.read() & 0xff);
}
System.out.println(Thread.currentThread()
.getId() + " << " + new String(buf));
if (len > 0) {
String send = Base64Util.encode(buf, len);
send += "\n";
os.write(send.getBytes());
os.flush();
}
} catch (IOException e) {
eof = true;
}
} else { // decode from base64
try {
StringBuilder sb = new StringBuilder(1024);
byte c = 0x0a;
do {
c = (byte) is.read();
if (c >= 0 && c != 0x0a) {
sb.append(new String(new byte[] { c }));
}
} while (c != 0x0a && c >= 0);
if (sb.length() != 0) {
try {
byte[] buf = Base64Util.decode(sb.toString());
System.out.println(Thread.currentThread()
.getId() + " >> " + buf.length);
os.write(buf);
os.flush();
} catch (StringIndexOutOfBoundsException e) {
System.out
.println(Thread.currentThread().getId()
+ " error on " + sb.toString());
}
}
} catch (IOException e) {
eof = true;
}
}
if (eof) {
System.out.println(Thread.currentThread().getId() + " EOF");
break;
}
}
try {
is.close();
os.close();
} catch (IOException e) {
}
}
}
public static void main(String[] args) throws Exception {
Process proc2 = Runtime.getRuntime().exec("nc -l -p 2020");
Process proc1 = Runtime.getRuntime().exec("nc 127.0.0.1 2020");
Socket sock1 = new Socket();
sock1.connect(new InetSocketAddress("127.0.0.1", 24554), 30);
Socket sock2 = new Socket();
sock2.connect(new InetSocketAddress("127.0.0.1", 24557), 30);
new Thread(new InToOut(sock1.getInputStream(), proc1.getOutputStream(),
true)).start();
new Thread(new InToOut(proc1.getInputStream(), sock1.getOutputStream(),
false)).start();
new Thread(new InToOut(sock2.getInputStream(), proc2.getOutputStream(),
true)).start();
new Thread(new InToOut(proc2.getInputStream(), sock2.getOutputStream(),
false)).start();
}
UPDATED:
I've found right way. I uses syncchronized queries for each stream and synchronized threads to fill or erase that queries. All threads mutually blocks themselves. And it works! :)
Sorry for bother.
I've found right way. I uses syncchronized queries for each stream and synchronized threads to fill or erase that queries. All threads mutually blocks themselves. And it works! :) Sorry for bother.