I'm trying to send a stream of Strings from a Java server to a C++/CLI Client, but before doing that I wanted to start with the simplest case, i.e. send a single String from a Java Server to a C++/CLI client and display it.
The examples I found in the literature or in tutorials didn't work for me, knowing that the same Java Server communicated easily with another Java Client (either on the same machine or on different machines).
Without further ado, here's my Code:
the Java Server Side: SendStringToCpp.java
import java.net.*;
import java.io.*;
public class SendStringToCpp {
public static void main(String[] args) {
String message = "message"; // The String that contains the information
byte[] sentBytes = message.getBytes();
System.out.println("Message: " + message);
ServerSocket s = null;
try {
s = new ServerSocket(30011);
} catch (IOException e) {
e.printStackTrace();
}
Socket s1 = null;
try {
s1 = s.accept();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
OutputStream s1out = null;
try {
s1out = s1.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
DataOutputStream dos = new DataOutputStream (s1out);
try {
//dos.writeUTF(message); // Sending the String
dos.write(sentBytes); // Sending the bytes
} catch (IOException e) {
e.printStackTrace();
}
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
s1out.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
s1.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
The C++ Client Side: ReceiveStringFromJava.cpp
#include "stdafx.h"
#include <exception>
using namespace System;
using namespace System::Net;
using namespace System::Net::Sockets;
using namespace System::Text;
using namespace System::IO;
int main(array<System::String ^> ^args)
{
Console::WriteLine(L"Creating the Socket...");
try {
//Socket^ listener = gcnew Socket(AddressFamily::InterNetwork, SocketType::Dgram, ProtocolType::Udp);
//Creates a UdpClient for reading incoming data.
UdpClient^ receivingUdpClient = gcnew UdpClient();
IPEndPoint^ RemoteIpEndPoint = gcnew IPEndPoint(IPAddress::Any, 30011);
//listener->Bind(RemoteIpEndPoint);
array <Byte>^ receiveBytes = receivingUdpClient->Receive(RemoteIpEndPoint); // get the Bytes array from the end poitn
String^ receivedString = Encoding::ASCII->GetString(receiveBytes); // retrieve the string from the received Bytes
Console::WriteLine("This is the message received {0}", receivedString);
// Console::WriteLine("this message was send from {0} on their ort number {1}", RemoteIpEndPoint->Address, RemoteIpEndPoint->Port);
}
catch (Exception^ e) {
Console::WriteLine("Error! ");
Console::WriteLine( e->ToString());
}
Console::ReadLine();
return 0;
}
And Here's the Exception printed on the Console:
http://i.stack.imgur.com/uTDqm.jpg
P.S. I tried to Bind the IPEndPoint to the Socket (it's commented above), but to no avail, and gave the same Error.
Socket^ listener = gcnew Socket(AddressFamily::InterNetwork, SocketType::Dgram, ProtocolType::Udp);
.
.
listener->Bind(RemoteIpEndPoint);
You need to use the UdpClient constructor that allows binding to a listening port.
Quoting MSDN (emphasis mine):
Initializes a new instance of the UdpClient class and binds it to the
local port number provided.
UdpClient^ receivingUdpClient = gcnew UdpClient(30011);
// specify the port both here ^^^^^ and here vvvvv
IPEndPoint^ RemoteIpEndPoint = gcnew IPEndPoint(IPAddress::Any, 30011);
array <Byte>^ receiveBytes = receivingUdpClient->Receive(RemoteIpEndPoint);
Related
Imagine the next case:
Client - server connection
Client sends a request to the server
Server answers the Client
Client reads the answer
Class Client:
public class Client extends Service{
private String IP_ADDRESS;
private int PORT;
public void start(){
l.info("Starting client for server at: "+IP_ADDRESS+":"+PORT);
//Initialization of the client
try {
cs=new Socket(IP_ADDRESS,PORT);
} catch (UnknownHostException e) {
l.error("Unkown host at the specified address");
e.printStackTrace();
} catch (IOException e) {
l.error("I/O error starting the client socket");
e.printStackTrace();
}
}
//Sends the specified text by param
public void sendText(String text){
//Initializa the output client with the client socket data
try {
//DataOutputStream to send data to the server
toServer=new DataOutputStream(cs.getOutputStream());
l.info("Sending message to the server");
PrintWriter writer= new PrintWriter(toServer);
writer.println(text);
writer.flush();
} catch (IOException e) {
l.error("Bat initialization of the output client stream");
e.printStackTrace();
}
//Should show the answers from the server, i run this as a thread
public void showServerOutput(){
String message;
while(true){
//If there are new messages
try {
BufferedReader br= new BufferedReader(new InputStreamReader((cs.getInputStream())));
if((message=br.readLine())!=null){
//Show them
System.out.println(message);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
showServerOutput() is the method that returns any answer sent by the server
Then my server class have the following code
public class Server extends Service{
public void startListenner(){
l.info("Listening at port "+PORT);
while(true){
// Waits for a client connection
try {
cs=ss.accept();
l.info("Connection received: "+cs.getInetAddress()+":"+cs.getPort());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
toClient= new DataOutputStream(cs.getOutputStream());
PrintWriter cWriter= new PrintWriter(toClient);
//Send a confirmation message
cWriter.println("Message received");
//Catch the information sent by the client
csInput=new BufferedReader(new InputStreamReader(cs.getInputStream()));
printData();
toClient.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
As you can see im sending a message to the client with the words: "Message received" but its never shown in the client console. Whats wrong?
EDIT
The printData() method prints the message received from the client in console
public void printData(){
l.info("Printing message received");
try {
System.out.println(csInput.readLine());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Not sure what your printData() method is doing, but aren't you missing a cWriter.flush() on the server side, once you printed "Message received" ?
As I understand it, you write your message but never send it to your client.
I have a problem with socket communication.
Sometimes reading from inputstream on client side stops working while the server is still sending new messages. I debugged the server so I know that is still working and sending messages to the outputstream. But on the client side read from inputstream is blocked. I can't debug this situation on client side. I only see difference in received messages on client side just before everything stops.
Example of good received message when everything works fine. Single send message in one line (I use DataInputStream.readUTF() method on client side and DataOutputStream.writeUTF(String msg) on server side. )
ADD;MB57,18-9,5,dd,10,10;
UP;MB15;20;14;20;13;1.0;
ADD;MB37,18-9,5,xx,10,10;
UP;MB13;20;14;20;13;1.0;
ADD;MB47,18-9,5,ww,10,10;
UP;MB13;20;14;20;13;1.0;
And this is happens just before my socket stop reading from input. One big mess. And everything that has been sent from the beginning in one line. It looks like the buffer overload O.o What happens?
11-07 11:36:41.978: I/System.out(17980): 11;8;10;8;0.1;��UPPOS;MB8;16;8;16;7;1.0;��PATH;MB8��UPPOS;MB20;14;9;14;10;1.0;�� ADDMOB;MB20,14-10,6,mummy,50,50;�� PATH;MB20��UPPOS;MB50;12;8;12;7;1.0;�� PATH;MB50��UPPOS;MB13;15;11;14;11;1.0;�� PATH;MB19��PATH;MB8��UPPOS;MB20;14;10;13;10;1.0;�� PATH;MB20��UPPOS;MB50;12;7;12;6;1.0;�� PATH;MB50��UPPOS;MB13;14;11;14;10;1.0;��UPPOS;MB19;13;9;14;9;1.0;�� PATH;MB19��PATH;MB8��UPPOS;MB20;13;10;13;9;1.0;��ADDMOB;MB20,13-9,6,mummy,50,50;�� PATH;MB20��UPPOS;MB50;12;6;12;7;1.0;�� PATH;MB50��UPPOS;MB13;14;10;15;9;1.0;��!ADDMOB;MB13,15-9,5,chicken,10,10;�� PATH;MB13��UPPOS;MB19;14;9;14;10;1.0;��!ADDMOB;MB19,14-10,1,goblin,37,50;�� PATH;MB19��UPPOS;NP12;10;8;9;8;0.1;��UPPOS;MB8;16;7;17;7;1.0;��PATH;MB8��UPPOS;MB20;13;9;12;9;1.0;�� PATH;MB20��UPPOS;MB50;12;7;11;7;1.0;�� PATH;MB50��UPPOS;MB13;15;9;14;9;1.0;�� PATH;MB13��UPPOS;MB19;14;10;13;9;1.0;�� ADDMOB;MB19,13-9,1,goblin,37,50;�� PATH;MB19��UPPOS;MB8;17;7;16;7;1.0;��PATH;MB8��UPPOS;MB20;12;9;12;8;1.0;��UPPOS;MB50;11;7;12;7;1.0;�� PATH;MB50��UPPOS;MB13;14;9;14;10;1.0;��"ADDMOB;MB13,14-10,5,chicken,10,10;�� PATH;MB13�� PATH;MB19��UPPOS;MB8;16;7;16;8;1.0;��PATH;MB8�� PATH;MB20�� PATH;MB50��UPPOS;MB13;14;10;15;10;1.0;�� PATH;MB13��UPPOS;MB19;13;9;14;9;1.0;�� PATH;MB19��UPPOS;NP12;9;8;9;9;0.1;��UPPOS;MB8;16;8;16;7;1.0;��PATH;MB8��UPPOS;MB20;12;8;12;9;1.0;�� PATH;MB20��UPPOS;MB50;12;7;12;6;1.0;�� PATH;MB50��UPPOS;MB13;15;10;14;10;1.0;��UPPOS;MB19;14;9;13;9;1.0;�� PATH;MB19��PATH;MB8��UPPOS;MB20;12;9;12;8;1.0;�� PATH;MB50��UPPOS;MB13;14;10;14;9;1.0;��!ADDMOB;MB13,14-9,5,chicken,10,10;�� PATH;MB13�� PATH;MB19��UPPOS;MB8;16;7;16;6;1.0;��PATH;MB8��UPPOS;MB20;12;8;12;7;1.0;�� PATH;MB20�� PATH;MB50��UPPOS;MB13;14;9;14;10;1.0;��"ADDMOB;MB13,14-10,5,chicken,10,10;�� PATH;MB13��UPPOS;MB19;13;9;13;10;1.0;��!ADDMOB;MB19,13-10,1,goblin,37,50;�� PATH;MB19��UPPOS;NP12;9;9;9;8;0.1;��PATH;MB8�� PATH;MB20��UPPOS;MB50;12;6;11;6;1.0;�� PATH;MB50��UPPOS;MB13;14;10;14;9;1.0;��!ADDMOB;MB13,14-9,5,chicken,10,10;�� PATH;MB13��UPPOS;MB19;13;10;13;9;1.0;�� ADDMOB;MB19,13-9,1,goblin,37,50;�� PATH;MB19��UPPOS;MB8;16;6;16;7;1.0;��PATH;MB8�� PATH;MB20��UPPOS;MB50;11;6;12;6;1.0;�� PATH;MB50��UPPOS;MB13;14;9;15;9;1.0;�� PATH;MB13�� PATH;MB19��PATH;MB8��UPPOS;MB20;12;7;12;8;1.0;�� PATH;MB20�� PATH;MB50��UPPOS;MB13;15;9;14;9;1.0;�� PATH;MB13��UPPOS;MB19;13;9;13;10;1.0;��!ADDMOB;MB19,13-10,1,goblin,37,50;�� PATH;MB19��UPPOS;NP12;9;8;10;8;0.1;��UPPOS;MB8;16;7;16;8;1.0;��PATH;MB8��UPPOS;MB20;12;8;12;7;1.0;�� PATH;MB20�� PATH;MB50��UPPOS;MB13;14;9;15;9;1.0;�� PATH;MB13��UPPOS;MB19;13;10;13;11;1.0;�� PATH;MB19��UPPOS;MB8;16;8;16;9;1.0;��PATH;MB8��UPPOS;MB20;12;7;11;7;1.0;�� PATH;MB20��UPPOS;MB13;15;9;14;9;1.0;�� PATH;MB50�� PATH;MB13��UPPOS;MB19;13;11;13;10;1.0;��UPPOS;MB20;11;7;12;7;1.0;�� PATH;MB20��UPPOS;MB8;16;9;16;8;1.0;�� PATH;MB50��UPPOS;MB13;14;9;15;9;1.0;�� PATH;MB13��UPPOS;MB19;13;10;14;10;1.0;��UPPOS;NP12;10;8;11;8;0.1;�� PATH;MB20��UPPOS;MB8;16;8;16;7;1.0;��PATH;MB8�� PATH;MB50��UPPOS;MB13;15;9;14;9;1.0;�� PATH;MB13��UPPOS;MB19;14;10;15;9;1.0;�� ADDMOB;MB19,15-9,1,goblin,37,50;�� PATH;MB19��UPPOS;MB20;12;7;11;7;1.0;�� PATH;MB20��UPPOS;MB8;16;7;16;6;1.0;��PATH;MB8��UPPOS;MB50;12;6;12;7;1.0;�� PATH;MB50��UPPOS;MB13;14;9;13;9;1.0;�� PATH;MB13��UPPOS;MB19;15;9;14;9;1.0;�� PATH;MB19�� PATH;MB20��UPPOS;MB8;16;6;16;7;1.0;��PATH;MB8��UPPOS;MB50;12;7;12;8;1.0;�� PATH;MB50�� PATH;MB13��UPPOS;MB19;14;9;14;10;1.0;��!ADDMOB;MB19,14-10,1,goblin,37,50;�� PATH;MB19��UPPOS;MB20;11;7;12;7;1.0;�� PATH;MB20��UPPOS;MB8;16;7;16;8;1.0;��PATH;MB8��UPPOS;MB50;12;8;12;9;1.0;�� PATH;MB50��UPPOS;MB13;13;9;14;9;1.0;�� PATH;MB13��UPPOS;MB19;14;10;15;10;1.0;�� PATH;MB19��UPPOS;MB20;12;7;11;7;1.0;�� PATH;MB20��UPPOS;MB50;12;9;12;8;1.0;�� PATH;MB50��UPPOS;MB8;16;8;16;7;1.0;��PATH;MB8��UPPOS;MB13;14;9;13;9;1.0;�� PATH;MB13��UPPOS;MB19;15;10;15;9;1.0;�� ADDMOB;MB19,15-9,1,goblin,37,50;��UPPOS;NP12;11;8;10;8;0.1;��UPPOS;MB20;11;7;12;7;1.0;��UPPOS;MB8;16;7;16;6;1.0;��PATH;MB8�� PATH;MB13��UPPOS;MB50;12;8;11;8;1.0
Client side
private DataOutputStream out;
private Socket client;
private DataInputStream in;
private Thread inputListener;
public void createConnection(){
try {
client = new Socket(serverName, port);
setOut(new DataOutputStream(client.getOutputStream()));
in = new DataInputStream(client.getInputStream());
inputListener=new Thread(){
public void run(){
try {
synchronized(in){
while(client!=null){
try{
String read = new String(in.readUTF());
/** do somethink with input msg */
} catch (java.io.UTFDataFormatException e1) {
e1.printStackTrace();
}
}
}
} catch (IOException e) {
e.printStackTrace();
} finally{
reconnect();
}
}
};
inputListener.start();
} catch (Exception e) {
e.printStackTrace();
}
}
private void reconnect() {
try {
client.close();
client=null;
inputListener.interrupt();
setOut(null);
in.close();
in=null;
} catch (IOException e) {
e.printStackTrace();
} finally{
System.out.println("RECONECT METHOD IN SOCKET");
}
}
Server side
private DataOutputStream out;
private Socket client;
public Client(Socket client) {
try {
setOut(new DataOutputStream(client.getOutputStream()));
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendMessage(String string) {
try {
getOut().writeUTF(string);
} catch (IOException e) {
e.printStackTrace();
disconected();
}
}
You must be writing something else to the stream. Catching and ignoring UTFDataFormatException is no solution. Once you get it, you will never get back into sync with the sender.
NB Converting the result of readUTF() to a String is futile. It already is a String.
I'm trying to change my game to use TCP, but I can't even get it to work.
The client connects successfully with the server, but for some reason I can't
receive messages from server nor receive messages from client. My guess is that I'm doing something wrong with the output/input?
Here is the server code:
public class Server implements Runnable {
Server() {
serverSocket = new ServerSocket(1919, 300);
}
run() {
while (true) {
String message = "blank";
try {
//w8ting for some connection
tcpSOCKET = tcpServer.accept(null);
//Connected to some1!
input = new BufferedReader(new InputStreamReader(
tcpSOCKET.getInputStream()));
output = new DataOutputStream(
tcpSOCKET.getOutputStream());
output.flush();
//TODO PROBLEM it stays here trying to read line but even if the client send a message it wont move on
message = input.readLine();
main.addLabel(Color.BLUE, message);
} catch (EOFException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
And this is the client:
public class Client implements Runnable {
Client() { }
run() {
String message = "";
try {
tcpSOCKET = new Socket(serverIp, serverTCPport);
input = new BufferedReader(new InputStreamReader(
tcpSOCKET.getInputStream()));
output = new DataOutputStream(tcpSOCKET.getOutputStream());
output.flush();
while (true) {
System.out.println("w8ting for message from server");
//TODO problem, it wont read anything even if the server send a message
message = input.readLine();
System.out.println("A message has arrived: " + message);
gameScreen.serverMessage = message;
}
} catch (EOFException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
and the class is called when I hit "s" in the server or in the client, they both use the same class
public void sendTCPMessage(String message) {
try {
output.writeBytes(message);
output.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
If you want to read lines, you must write lines.
If you want to read with a BufferedReader, you should write with a BufferedWriter.
If you want to write with a DataOutputStream, you should read with a DataInputStream.
I'm new to network I/O programming, and I've run into a snag-- basically what I want to do is have a desktop app talk to the google maps javascript API. In order to facilitate this, I have built a java applet which will act as a bridge between the desktop app and the browser javascript app. When I run the desktop app and applet together in Eclipse they can communicate perfectly, and I am able to invoke applet functions by writing strings to a Socket bound to the same port the applet has established a ServerSocket connection with. For testing purposes in Eclipse, I send the string "sendJSAlertTest" to the socket's outputstream, then derive a Method instance using the java.lang.reflect API from the ServerSocket inputstream, and then finally invoke the resulting method in the applet. When the applet is running in a browser I write "sendJSAlert" to the socket instead since it leads to the actual invocation of javascript. The result in Eclipse using the appletviewer is that the desktop application context prints the output "awesome sendJSAlert" and the applet context prints the output from the sendJSAlertTest() method, "Hello Client, I'm a Server!". The result of passing "sendJSAlert" to the applet running in the browser is that the desktop application prints null, suggesting that for some reason the inputstream of the ServerSocket is empty, and the browser itself does nothing when it should generate a javascript alert box with the text "Hello Client, I'm a Server!". The browser I'm using is Google Chrome, and for the moment I am simply running everything on the local machine (e.g. no remote server involved yet)
Below is the relevant Java code and HTML:
SocketClient.java
import java.awt.event.*;
import java.io.*;
import java.net.*;
public class SocketClient {
Socket socket = null;
PrintWriter out = null;
BufferedReader in = null;
private InetAddress myAddress;
private String remoteFunction;
public SocketClient(){
}
public void listenSocket(int portNum){
//Create socket connection
try{
System.out.println("#Client Trying to create socket bound to port " + portNum);
socket = new Socket(<my hostname here as a string>, portNum);
System.out.println("the attached socket port is " + socket.getLocalPort());
System.out.flush();
out = new PrintWriter(socket.getOutputStream(), true);
out.println("sendJSAlertTest");
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = in.readLine();
System.out.println("#CLient side Text received from server: " + line);
} catch (UnknownHostException e) {
System.out.println("Unknown host: <my hostname here as a string>.eng");
System.exit(1);
} catch (IOException e) {
System.out.println("No I/O");
e.printStackTrace();
System.exit(1);
}
}
public void setRemoteFunction(String funcName){
remoteFunction = funcName;
}
public String getRemoteFunction(){
return remoteFunction;
}
}
SocketServer.java
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.*;
class SocketServer {
ServerSocket server = null;
Socket client = null;
BufferedReader in = null;
PrintWriter out = null;
String line;
private NetComm hNet;
private Method serverMethod;
SocketServer(NetComm netmain){
hNet = netmain;
}
public void listenSocket(int portNum){
try{
System.out.println("#server Trying to create socket bound to port " + portNum);
server = new ServerSocket(portNum);
System.out.println("the attached socket port is " + server.getLocalPort());
} catch (IOException e) {
System.out.println("Could not listen on port " + portNum);
System.exit(-1);
}
try{
client = server.accept();
System.out.println("Connection accepted!");
} catch (IOException e) {
System.out.println("Accept failed: " + portNum);
System.exit(-1);
}
try{
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
out = new PrintWriter(client.getOutputStream(), true);
} catch (IOException e) {
System.out.println("Accept failed: " + portNum);
System.exit(-1);
}
while(true){
try{
System.out.println("trying to read from inputstream...");
line = in.readLine();
System.out.println(line);
//Now that we have a method name, invoke it
try {
serverMethod = hNet.getClass().getDeclaredMethod(line,
String.class);
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
serverMethod.invoke(hNet, "Hello Client, I'm a Server!");
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Send data back to client
out.println("awesome " + line);
} catch (IOException e) {
System.out.println("Read failed");
System.out.flush();
System.exit(-1);
}
}
}
protected void finalize(){
//Clean up
try{
in.close();
out.close();
server.close();
} catch (IOException e) {
System.out.println("Could not close.");
System.exit(-1);
}
}
public int getBoundLocalPort(){
return server.getLocalPort();
}
}
NetComm.java
import cresco.ai.att.ccm.core.CCMMain;
import cresco.ai.att.ccm.gui.DataPanel;
import java.io.*;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URL;
import java.util.ArrayList;
import javax.servlet.*;
import javax.servlet.http.*;
import java.applet.*;
public class NetComm extends JApplet{//HttpServlet{
private CCMMain hMain;
private DataPanel dpLocal;
private SocketServer sockserver;
private Method serverMethod;
String testStr;
Integer testInt; /*integer */
Character testChar; /*character*/
//Testing this...
ServerSocket server = null;
Socket client = null;
BufferedReader in = null;
PrintWriter out = null;
String line;
#Override
public void init(){
sockserver = new SocketServer(this);
//For offline debug (should be disabled in a release to the webapp):
//initSocketServer is commented out in the release version and
//invoked in the Eclipse testbed version. In the webapp,
//initSocketServer is invoked from javascript (see below js sockPuppet())
//////initSocketServer(0);
String msg = "Hello from Java (using javascript alert)";
try {
getAppletContext().showDocument(new URL("javascript:doAlert(\"" +
msg +"\")"));
}
catch (MalformedURLException me) { }
}
public void sendJSAlertTest(String message){
System.out.println("sendJSAlert remotely invoked, with message: " +
message);
}
public void sendJSAlert(String message){
try {
getAppletContext().showDocument(new URL("javascript:doAlert(\"" +
message +"\")"));
}
catch (MalformedURLException me) { }
}
public void initSocketServer(int portNum){
sockserver.listenSocket(portNum);
}
public void finalizeSocketServer(){
sockserver.finalize();
}
public int socket2Me(int portNum){
try {
socks.add(new ServerSocket(portNum));
return 0; //socket opened successfully
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return -1; //socket failed to open
}
}
public int getSocketServerPort(){
return sockserver.getBoundLocalPort();
}
public void showRectTest(){
try {
getAppletContext().showDocument(new
URL("javascript:overlayRect()"));
}
catch (MalformedURLException me) { }
}
public void setGUI(DataPanel d){
dpLocal = d;
}
}
MapViz.html
<html>
<head>
<title>Welcome to Geographic Midpoint Map Vizualization!</title>
<meta name="viewport"
content="width=device-width, initial-scale=1.0, user-scalable=no">
<meta charset="UTF-8">
<link href="https://google-developers.appspot.com/maps/documentation/javascript
/examples/default.css"
rel="stylesheet" type="text/css">
...google maps stuff omitted...
<script type="text/javascript">
<script type="text/javascript">
function overlayRect(){
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.fillStyle="#FF0000";
ctx.fillRect(0,0,150,75);
}
function doAlert(s){
alert(s);
}
function testJava(){
document.ccmApplet.showRectTest();
}
function sockPuppet(){
var i = parseInt(document.getElementById("args").value,10);
alert("parsing the input args... got " + i);
if(i == NaN || i == null){
i = 0;
}
alert("passed NaN OR null block, i is " + i);
//i = 6672; //because $%*& you, that's why!
document.ccmApplet.initSocketServer(i);
//document.ccmApplet.listenSocket(i);
alert("inittializing socket server...");
//queryPort();
alert("querying port...");
document.ccmApplet.finalizeSocketServer();
//document.ccmApplet.finalize();
alert("finalizing socket server...");
}
function queryPort(){
var d = document.getElementById("debug");
var s1 = "Last port opened was: ";
//var s2 = document.ccmApplet.getLastBoundPort();
var s2 = document.ccmApplet.getSocketServerPort();
var sFinal = s1.concat(s2);
d.value = sFinal;
}
</script>
</head>
<body>
<applet width="500" height="50" name="ccmApplet" archive="CCM.jar"
code="cresco.ai.att.ccm.io.NetComm" MAYSCRIPT></applet>
<p></p>
<canvas id="myCanvas" width="200" height="100"></canvas>
<div id="map_canvas"></div>
<input id="args" type="textentry" value="" />
<button height="50" width="50" onClick="sockPuppet()">Test Socket
Creation</button>
<input id="debug" type="debugthingy" value="debug area..." />
<button height="50" width="50" onClick="testJava()">Test Java Callback</button>
</body>
</html>
In the webapp, I fill in the args input with a valid port number on the local machine and press the Test Socket Connection button which invokes the sockPuppet() javascript. This should create a ServerSocket and bind it to the specified port, which I then separately connect my desktop client app to via SocketClient.listenSocket. The result from Eclipse in the desktop app context is "awesome sendJSAlertTest" and in the appletviewer context is the output "sendJSAlert remotely invoked, with message: Hello Client, I'm a Server!". The webapp, invoking sendJSAlert(), should call the javascript alert function on the same message, creating a popup box with the message "sendJSAlert remotely invoked, with message: Hello Client, I'm a Server!" but instead nothing happens in the browser (nor the Chrome java or javascript debug consoles), and the desktop app output is null instead of "awesome sendJSAlert" as expected
So the question: What might be the cause of the different results? I know the browser's security sandbox could be an issue, but I've included a permissions file which should allow communication via sockets on any localhost port:
grant {
permission java.net.SocketPermission
"localhost:1024-",
"accept, connect, listen, resolve";
};
It's certainly possible though that I have not applied the permissions properly (I used the sun policytool gui); what exactly needs to be done in the applet code (if anything) to apply the permissions? Could a security problem result in the lack of response I'm seeing? I'd expect an exception to be reported in Chrome's java debug console, but there weren't any...
any help would be much appreciated, thanks!
-CCJ
UPDATE:
Okay, some new information: I ran the applet again in Chrome with the javascript console open (could have sworn I tried this before without effect, but evidently not) and received the following console output--
"Uncaught Error: java.security.AccessControlException: access denied
("java.net.SocketPermission" "<myipaddress>:4218" "accept,resolve") MapVizApp.html:154
sockPuppet MapVizApp.html:154 onclick MapVizApp.html:179 Uncaught Error: Error
calling method on NPObject. sockPuppet onclick "
So the question now is why am I tripping this security exception? The policy file with the permissions given above is in the same working directory as the html page and the jar file containing the applet, and I added the following to my system's JRE security policy file
//Grants my NetComm applet the ability to accept, connect, and listen on unpriv. ports
grant codeBase "file:${user.home}\Desktop\dev\invention\ATT\MapViz\CCM.jar" {
permission java.net.SocketPermission
"localhost:1024-",
"accept, connect, listen, resolve";
};
I haven't yet signed the applet, but it was my understanding that if the policy files are in order an applet doesn't need to be signed... if I'm wrong on that please let me know. Anyway, does anyone have any suggestions as to why this security exception is being thrown despite the policy files having the above granted permissions? Is there a naming convention for policy files in working directories that the JRE looks for? My working directory policy file for now is just named ccmPolFile, but I'm not clear on how the JRE is supposed to locate it; is there something I need to add to the applet code to point the JRE at the intended working directory policy file? Further, shouldn't the system policy file grant that I added be enough by itself to satisfy socket permissions for my applet inside CCM.jar?
UPDATE 2:
I signed the applet and added the line policy.url.3=file:${user.home}\Desktop\dev\invention\ATT\MapViz\ccmPolFile.policy to my java.security file in ${java.home}/lib/security (via http://docs.oracle.com/javase/tutorial/security/tour2/step4.html#Approach2 this is apparently how the JRE locates policy files to load)... sadly, the result is exactly the same security exception. The only thing left that I know of is
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
// perform the security-sensitive operation here
return null;
}
});
which should let me do almost anything since the applet is now signed. I wanted to keep signing out of the equation, but policy files aren't working for some reason. I'll be back shortly with how that works out
righto, so following my update 2 above, I change the listenSocket() method in SocketServer.java code to
public void listenSocket(int portNum){
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
int portNum = 4444;
try{
System.out.println("#server Trying to create socket bound to port " + portNum);
server = new ServerSocket(portNum);
System.out.println("the attached socket port is " + server.getLocalPort());
} catch (IOException e) {
System.out.println("Could not listen on port " + portNum);
System.exit(-1);
}
try{
client = server.accept();
System.out.println("Connection accepted!");
} catch (IOException e) {
System.out.println("Accept failed: " + portNum);
System.exit(-1);
}
try{
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
out = new PrintWriter(client.getOutputStream(), true);
} catch (IOException e) {
System.out.println("Accept failed: " + portNum);
System.exit(-1);
}
while(portNum==4444){
try{
System.out.println("trying to read from inputstream...");
line = in.readLine();
System.out.println(line);
//Now that we have a method name, invoke it
try {
serverMethod = hNet.getClass().getDeclaredMethod(line,
String.class);
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
serverMethod.invoke(hNet, "Hello from Javascript invoked by the
desktop app!");
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Send data back to client
out.println("awesome " + line);
//System.out.println(line);
//System.out.flush();
} catch (IOException e) {
System.out.println("Read failed");
System.out.flush();
System.exit(-1);
}
}
return null;
}
});//end doPrivileged
}
obviously this is an unsafe kludge, but it does the trick-- I receive no security exception, and the desktop app prints "awesome sendJSAlert" so I know IO is working between the client and server contexts via sockets. The actual js alert function didn't fire, but I think that has something to do with the horrid infinite while loop in listenSocket() above...
Take home message: for some reason, to establish socket connections from an applet in google chrome I needed to sign the applet AND use AccessController.doPrivileged() to invoke my security sensitive code, despite having set my local policy and security files to grant my applet those permissions
googlers see refs:
http://www.coderanch.com/how-to/java/HowCanAnAppletReadFilesOnTheLocalFileSystem
http://docs.oracle.com/javase/7/docs/api/java/security/AccessController.html
http://www-personal.umich.edu/~lsiden/tutorials/signed-applet/signed-applet.html
http://docs.oracle.com/javase/tutorial/security/tour2/step4.html
UPDATE: Finally working 100% :D I changed the listenSocket() method above in SocketServer.java to this:
public void listenSocket(int portNum){
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
int portNum = 4444;
try{
System.out.println("#server Trying to create socket bound to port " + portNum);
server = new ServerSocket(portNum);
System.out.println("the attached socket port is " + server.getLocalPort());
} catch (IOException e) {
System.out.println("Could not listen on port " + portNum);
System.exit(-1);
}
try{
client = server.accept();
System.out.println("Connection accepted!");
} catch (IOException e) {
System.out.println("Accept failed: " + portNum);
System.exit(-1);
}
try{
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
out = new PrintWriter(client.getOutputStream(), true);
} catch (IOException e) {
System.out.println("Accept failed: " + portNum);
System.exit(-1);
}
try {
line = in.readLine();
System.out.println("line is " + line + " from the inputstream to the
serversocket");
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if(line != null){
System.out.println("trying to read from non-null inputstream...");
//line = in.readLine();
System.out.println(line);
//Now that we have a method name, invoke that bitch!
try {
serverMethod = hNet.getClass().getDeclaredMethod(line, String.class);
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
serverMethod.invoke(hNet, "Hello From Javascript invoked by a desktop
app!");
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Send data back to client
out.println("awesome " + line);
//System.out.println(line);
//System.out.flush();
}
return null;
}
});//end doPrivileged
}
The server.accept() method blocks until a connection is made anyway, so for this scenario where I only want to pass one command at a time to the serversocket inputstream a while loop didn't make sense. The change to an if allowed the program to actually continue on to the java.reflect stuff which invokes a method in the applet which invokes javascript functions directly. Since the port is still hard-coded and the applet utilizes doPrivileged(...) this is still not a great solution, but it does satisfy the use case of invoking javascript in a web browser from a desktop java application via a java applet bridge so it makes for a good springboard into more robust implementations!
Im developing a client-server app. The client side is Java based, the server side is C++ in Windows.
Im trying to communicate them with Sockets, but im having some trouble.
I have succesfully communicated the client with a Java Server, to test if it was my client that was wrong, but its not, it seems like im not doing it right in the C++ version.
The java server goes like this:
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){
boolean again = true;
String mens;
ServerSocket serverSocket = null;
Socket socket = null;
DataInputStream dataInputStream = null;
DataOutputStream dataOutputStream = null;
try {
serverSocket = new ServerSocket(12321);
System.out.println("Listening :12321");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while(again){
try {
System.out.println("Waiting connection...");
socket = serverSocket.accept();
System.out.println("Connected");
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream = new DataOutputStream(socket.getOutputStream());
while (again){
mens = dataInputStream.readUTF();
System.out.println("MSG: " + mens);
if (mens.compareTo("Finish")==0){
again = false;
}
}
} catch (IOException e) {
System.out.println("End of connection");
//e.printStackTrace();
}
finally{
if( socket!= null){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
}
}
if( dataInputStream!= null){
try {
dataInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if( dataOutputStream!= null){
try {
dataOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
System.out.println("End of program");
}
}
The client just makes a connection and sends some messages introduced by the user.
Could you please give me a similar working server but in C++ (in Windows)?
I can't make it work by myself.
Thanx.
Your problem is that you are sending a java string which could take 1 or 2 bytes per character (see bytes of a string in java?)
You will need to send and receive in ascii bytes to make things easier, imagine data is your data string on the client side:
byte[] dataBytes = data.getBytes(Charset.forName("ASCII"));
for (int lc=0;lc < dataBytes.length ; lc++)
{
os.writeByte(dataBytes[lc]);
}
byte responseByte = 0;
char response = 0;
responseByte = is.readByte();
response = (char)responseByte;
where is and os are the client side DataInputStream and DataOutputStream respectively.
You can also sniff your tcp traffic to see what's going on :)