I know there are many people who already asked this Question, but in all the threads I read I couldn't find 1 solution for my problem (even if others had the same one, it didn't work for me).
As the Title says, I'm trying to connect from a Flash/SWF-Application to a small Java server I wrote via Sockets. It works fine offline (on the same machine), but as soon as I put the .swf on a Webspace and open it from there, Flash requests the Policy file from the server. There's nothing bad with that, but my problem is that Flash disconnects after (hopefully) getting the policy-file but doesn't reconnect again.
My server always opens a new Thread when a client connects, but that's not where the trouble is made, as I already tried it without opening a new Thread.
Here's my code:
while (true) {
connection = providerSocket.accept();
System.out.println("Incoming connection from " +
connection.getInetAddress().getHostName());
BufferedReader in = new BufferedReader(
new InputStreamReader(connection.getInputStream()));
String request = in.readLine();
if (request != null && request.contains("<policy-file-request/>")) {
System.out.println("Authorization request.");
PrintStream out = new PrintStream(connection.getOutputStream(), true);
out.println("<?xml version=\"1.0\"?><cross-domain-policy><!DOCTYPE cross-domain-policy SYSTEM \"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd\"><allow-access-from domain=\"*\" to-ports=\"3002\" /></cross-domain-policy>\u0000");
out.flush();
System.out.println("AuthData sent.");
connection.close();
System.out.println("Authorization complete.");
connection = providerSocket.accept();
System.out.println("TEST");
RequestProcessor c = new RequestProcessor(connection, connectionCounter++);
Thread t = new Thread(c);
t.start();
} else {
RequestProcessor c = new RequestProcessor(connection, connectionCounter++);
Thread t = new Thread(c);
t.start();
}
}
You will surely notice that I am using "\u0000" at the end instead of "\0", but don't worry, I also tested that case, didn't change anything. :/
I dont even reach the "TEST"-Ouput, because I don't get a new connection. And if I don't close the connection myself, flash automatically disconnects me.
The last thing I tried was just sending the xml without any request (right at the beginning, after the connection is established). I got a "recv failed" - Error for that.
PS: RequestProcessor is my new Thread, in which I would process the Strings/Commands sent from my.swf-File...
Thanks for helping me! :)
I had this problem before, you can not just use in.readLine() to get the policy file request string, because there're zero character.
To make sure you read the whole policy file request:
private String read(BufferedReader in) throws IOException {
StringBuilder builder = new StringBuilder();
int codePoint;
boolean zeroByteRead = false;
System.out.println("Reading...");
do {
codePoint = in.read();
if (codePoint == -1) {
return null;
}
if (codePoint == 0) {
zeroByteRead = true;
} else {
builder.appendCodePoint(codePoint);
}
} while (!zeroByteRead);
return builder.toString();
}
In the calling method:
BufferedReader in = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
String inputLine;
while ((inputLine = read(in)) != null) {
System.out.println("Receive from client: " + inputLine);
if ("<policy-file-request/>".equals(inputLine)) {
// Serve policy file, like the one in your question.
out.println(buildPolicy() +"\u0000");
} else {
// Do your job.
}
}
You can find the policy file project in java which can be downloaded. I myself thank to the guys over there.
Related
I am currently learning Java, and I tried to make a simple chat program, which communicates between a server and a client. My problem is that the two programs connect properly to each other, but send messages do not get print out. I do not know whether it is the sending or receiving part. Do not judge my class naming, it is just temporarily.
The client-side part of receiving:
InputStream is = chatterSock.getInputStream();
OutputStream os = chatterSock.getOutputStream();
Thread readThread = new Thread(() -> {
while (true) {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder out = new StringBuilder();
String newLine = System.getProperty("line.separator");
String line;
while ((line = reader.readLine()) != null) {
out.append(line);
out.append(newLine);
}
chatter.print("<p>" + out.toString() + "</p>");
} catch (IOException ex) {
chatter.printWarning("Connection lost");
}
}
The server-side part is pretty similar.
To send messages I just run
<Socket>.getOutputStream().write(<String>.getBytes());
I already tried some other posts from stackoverflow, but did not find a way that works. Thanks for your help!
Edit: here is the server side:
InputStream is = chatterSock.getInputStream();
OutputStream os = chatterSock.getOutputStream();
Thread readThread = new Thread(() -> {
while (true) {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder out = new StringBuilder();
String newLine = System.getProperty("line.separator");
String line;
while ((line = reader.readLine()) != null) {
out.append(line);
out.append(newLine);
}
overlord.print("<p>" + out.toString() + "</p>");
} catch (IOException ex) {
overlord.chatterSockList.remove(overlord.chatterSockList.indexOf(chatterSock));
overlord.printWarning("Connection to " + chatterSock.getInetAddress() + " lost");
overlord.sendToAll(("User " + username + " disconnected."));
}
}
});
Edit: The message gets send here:
sendButton.addActionListener(e -> {
try {
chatterSock.getOutputStream().write((messageArea.getText()+"\n").getBytes());
messageArea.setText("");
} catch (IOException ex) {
System.err.println(ex);
printWarning("Connection lost"); //TODO heartbeat
}
});
As #Russell Uhl mentions in his comment, a read loop whose termination condition is reader.readLine()) != null is only going to terminate when the output stream is closed.
If the output stream is not closed, that call simply waits for new information, and shall continue to do so indefinitely.
It is also going to wait indefinitely if you don't send over a newline, which is why you were told to add it to your write command.
It would be best to process each line you read separately, rather than trying to append them to a buffer and output them all together. Do the processing inside the loop.
And probably it's also a good idea to add some button to your GUI to terminate the chat. It will disable the rest of the GUI and close the output stream, which in turn will cause the readLine() to return null, and the loop to terminate properly.
I'm kinda new to Java language, but have a good experience in other technologies.
Right now Im working on creating a proxy server and I have come up with the code that seems to work fine for single requests, but when I'm trying to open some html page that loads lots of styles, images etc, part of requests just got aborted ( this is what firebug tells me )
So, will try to simplify the code and be as much specific as possible in showing up the exact problem
Here's the main class :
public class ProxyThread {
public static void main(String[] args) {
ProxyThread Proxy = new ProxyThread();
Proxy.start();
}
public void start() {
ServerSocket server = new ServerSocket(this.portNumber, 1);
while(true) {
Socket serverClient = server.accept();
this._threads[threadCount] = new Thread( new RequestProcess( serverClient, threadCount++ ));
}
}
}
Here's the code of RequestProcess that does processing of each request
public class RequestProcess implements Runnable {
public void start() throws InterruptedException {
this.serverIn = new BufferedReader( new InputStreamReader( this.serverClient.getInputStream() ) );
this.serverOut = this.serverClient.getOutputStream() ;
String currentBuffer;
String request = "";
String host = "";
int port = 0;
while ((currentBuffer = this.serverIn.readLine()) != null) {
if (currentBuffer.length() == 0) {
break;
}
request += currentBuffer + "\r\n";
if (currentBuffer.startsWith("CONNECT ") || currentBuffer.startsWith("GET ")) {
host = this.parseHost( currentBuffer );
port = this.parsePort( currentBuffer );
}
}
request += "\r\n";
if (host.isEmpty() || request.isEmpty()) {
throw new InterruptedException("request or host empty, so exiting ");
}
clientRequestProcess clientProcess = new clientRequestProcess( host, port, request, this.threadNum );
byte[] response = clientProcess.processRequest();
this.serverOut.write(response);
this.serverOut.close();
}
}
And here's the class that process request and sending it to the actual server
public class clientRequestProcess {
public byte[] processRequest()
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte buf[] = new byte[256*1024];
Socket clientSocket = new Socket( host, port );
clientSocket.getOutputStream().write( request.getBytes() );
InputStream is = clientSocket.getInputStream();
int r = 1;
while (r > 0) {
r = is.read(buf);
if (r > 0) {
bos.write(buf, 0, r);
}
}
return bos.toByteArray();
}
}
All the code is draft one and is simplified to show the big picture of how it works. All try-catch blocks, debugging info etc are missed here.
steps
- Set up browser to use JAVA proxy
- Open some site
- Part of http requests are successfully processed and correct response is returned
-part of requests shows up as aborted in firebug. The thing is that part is absolutely random, so one time some file is loading, another it is not
Code troubleshooting shows me that first line of request (that comes from the browser) are empty, so my condition
if (currentBuffer.length() == 0) {
break;
}
breaks reading the socket and thus it ruturns nothing to the browser and connection gets aborted
I read rfc on http protocol and figured out that https requests considered to be over once \r\n meets, so that's why I'm using that condition
If I just open that file in separate tab - it loads successfully, don;t matter how many times im trying to reload it. But when a bunch of files are loaded at one time - some random of them gets aborted. So it is happening only when a lot of files loading, when one or even 3-5 - all files loads fine
Any ideas?
Thanks
i have a java client-server app in java, both using the same connection class that contains both send/receive messages.
for some reason, some of the messages i send are received in a malformed order:
here's the code
//set up
_in = new BufferedReader(new InputStreamReader(this._socket.getInputStream()));
_out = new BufferedWriter(new OutputStreamWriter(this._socket.getOutputStream()));
this._socket.setSoTimeout(S_TIMEOUT);
public synchronized boolean send(String message){
try {
_out.write(message);
_out.write(Connection.DELIMITER);
_out.flush();
return true;
} catch (IOException e) {
}
return false;
}
public String receive(){
int c;
try {
String message = "";
System.out.println("Getting message:");
c = _in.read();
while(c != -1 && c != Connection.DELIMITER) {
message += (char) c;
c = _in.read();
}
if (c == -1) {
return null;
}
return message;
} catch (IOException e) { }
return null;
}
some messages, for example "new_order" will might return with "ew_ord".
some characters are lost, others are sent separately. this seems odd as its TCP
could this be an encoding related issue?
Delimiter is (char) 0
socket timeout is 20000 (ie 20 senconds). every 10 seconds i send an empty message to make sure socket does not close
EDIT:
although it was solved using the Scanner, i must say that the original code worked fine for many messages/various machines for a very long time (a few weeks), and then suddenly failed to work with one specific message on one specific machine (other messages went through just fine). i've done socket data transfer in java MANY times and i've written many read/write methods to handle the sockets. it's the first time i ran into this.
although in the original code i set the encoding (in the posted code i didn't), i believe that the problem was encoding related. at one point, the message that was received had every second character missing. afterwards i changed it a bit, and the first/second character of the message were received in a separate message. from my understanding, it's either an encoding issue or some firewall/other security program that was running on the message sender machine, that decided to filter outgoing packets.
Try replacing your receive with a Scanner and let it do the work for you.
// in your setup
Scanner sc = new Scanner(_in).useDelimiter(Connection.DELIMETER);
public String receive() {
try {
return sc.next();
} catch(IOException e) {
return "";
}
}
For starters, I would make sure you're printing exceptions in those catch blocks.
Then, you're using the platform default encoding for converting characters to bytes. If these two processes are running on different machines, it's possible they're using different encodings. I would make sure you're specifying an encoding when you set up the Reader and Writer.
You can use UTF encoding for getting Full String of Message.
U can try this code and I am Sure About this code because i used it in My Chat Application.
String data=" ";
socket = new Socket("localhost",999);
while(true)
{
dos = new DataOutputStream(socket.getOutputStream());
dis = new DataInputStream(socket.getInputStream());
data = dis.readUTF();
jta.append(data +"\n");
}
Where jta is JTextArea.
It's for Client Side
Now For Server Side:
try
{
server = new ServerSocket(999);
Socket soc = server.accept();
while(true)
{
String data="";
try
{
dis = new DataInputStream(soc.getInputStream());
dos = new DataOutputStream(soc.getOutputStream());
data = dis.readUTF();
}
catch(Exception e)
{ }
jta.append(data + "\n");
}
}
catch (IOException e)
{
JOptionPane.showMessageDialog(this, e);
System.exit(-1);
}
How does one set a timeout on a BufferedReader and a PrintWriter created using a socket connection? Here is the code I have for the server right now, which works until either the server or the client crashes:
while(isReceiving){
str = null;
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
while ((str = br.readLine()) != null){
System.out.println("Processing command " + str);
pw.println(client.message(str));
}
}
Outside the scope of this code I have imposed a socket timeout of 1000ms, which works as intended when waiting for the initial connection. But the program blocks at (str = br.readLine()). If the client hangs or crashes, it never stops blocking unless I terminate the process (which even then doesn't always work).
The client code in question is very similar to this, and is blocking in a similar fashion.
You need to set a read timeout on the socket, with Socket.setSoTimeout(). This will cause any read method to throw a SocketTimeoutException if the read timeout specified expires. NB Read timeouts are set not on the stream but on the underlying Socket, via Socket.setSoTimeout().
There is no such thing as a write timeout in TCP.
You could use SimpleTimeLimiter from Google's Guava library.
Sample code (in Java 8):
BufferedReader br = ...;
TimeLimiter timeLimiter = new SimpleTimeLimiter();
try {
String line = timeLimiter.callWithTimeout(br::readLine, 10, TimeUnit.SECONDS);
} catch (TimeoutException | UncheckedTimeoutException e) {
// timed out
} catch (Exception e) {
// something bad happened while reading the line
}
An answer in this question describes an interesting method using a Timer to close the connection. I'm not 100% sure if this works in the middle of a read, but it's worth a shot.
Copied from that answer:
TimerTask ft = new TimerTask(){
public void run(){
if (!isFinished){
socket.close();
}
}
};
(new Timer()).schedule(ft, timeout);
isFinished should be a boolean variable that should be set to true when you're done reading from the stream.
Since calling socket.close() did not seem to interrupt the block at br.readLine(), I did a little workaround. When disconnecting the client from the server, I merely send through a string "bye", and told the server to close the socket connection when it receives this command.
while ((str = br.readLine()) != null){
// If we receive a command of "bye" the RemoteControl is instructing
// the RemoteReceiver to close the connection.
if (str.equalsIgnoreCase("bye")){
socket.close();
break;
}
System.out.println("Processing command " + str);
pw.println(client.message(str));
}
I have a server which initially does this:-
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
for (;;) {
String cmdLine = br.readLine();
if (cmdLine == null || cmdLine.length() == 0)
break;
...
}
later it passes the socket to another class "foo"
This class wait for application specific messages.
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
appCmd=br.readLine();
My client sends this sequence:
"bar\n"
"how are u?\n"
"\n"
"passing it to foo\n"
"\n"
The problem is that sometimes "foo" does not get its response. It hangs in the readLine().
What is the chance that readLine() in the server is buffering up the data using the read ahead and "foo" class is getting starved?
If I add a sleep in the client side, it works. But what is the chance that it will always work?
"bar\n"
"how are u?\n"
"\n"
sleep(1000);
"passing it to foo\n"
"\n"
How to fix the problem? Appreciate any help on this regard.
eee's solution works perfectly. I was trying to read output from an SMTP conversation but it would block on:
while ((response = br.readLine()) != null) {
...Do Stuff
}
Changing to:
while (br.ready()) {
response = br.readLine();
...Do Stuff
}
I can read everything just fine. br is a BufferedReader object, BTW.
There is data already in the first BufferedReader (that has been read from the socket, and is no longer available from the socket), so pass the BufferedReader created in the first example to the class that reads the app specific messages, rather then creating a new BufferedReader from the socket.
I had the same problem and here is my solution:
try {
StringBuilder response = new StringBuilder();
response.append("SERVER -> CLIENT message:").append(CRLF);
//Infinite loop
while (true) {
//Checks wheather the stream is ready
if (in.ready()) {
//Actually read line
lastLineFromServer = in.readLine();
//If we have normal behavior at the end of stream
if (lastLineFromServer != null) {
response
.append(lastLineFromServer)
.append(CRLF);
} else {
return response.toString();
}
} else {//If stream is not ready
//If number of tries is not exceeded
if (numberOfTry < MAX_NUMBER_OF_TRIES) {
numberOfTry++;
//Wait for stream to become ready
Thread.sleep(MAX_DELAY_BEFORE_NEXT_TRY);
} else {//If number of tries is exeeded
//Adds warning that things go weired
response
.append("WARNING \r\n")
.append("Server sends responses not poroperly.\r\n")
.append("Response might be incomplete.")
.append(CRLF);
return response.toString();
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
return "";
}
The answer might be late but this is the simplest and latest answer in 2020, just use the simple way to receive the data from the socket server or client using the input stream read() method.
EOFException will be thrown when the client is disconnected or the server closed the connection.
private String waitForData() throws IOException {
String data = "";
do {
int c = inputStream.read();
if (c > -1) data += (char) c;
else throw new EOFException();
} while (inputStream.available() > 0);
return data;
}