I'm doing an on-line Java course and created a very simple server. Using Edge as client it works but not with Chrome. I've tried turning off firewall and some of the things suggested here (WAMP server localhost wont work with Chrome) and elsewhere, but they all seem to be overly complicated changes to Windows files. Surely there's a config setting somewhere?!
In Edge it's fine, in Chrome it returns this whether I use localhost:999 or 127.0.0.1:999. I've tried other ports too.
This page isn’t working
127.0.0.1 sent an invalid response.
ERR_INVALID_HTTP_RESPONSE
Here is my code in case needed.
public static void main(String[] args) {
try (
ServerSocket aServer = new ServerSocket(999);
Socket cn = aServer.accept();
BufferedReader bis = new BufferedReader(new InputStreamReader(cn.getInputStream()));
BufferedOutputStream bos = new BufferedOutputStream(cn.getOutputStream());)
{
String line = bis.readLine();
while(line != null && !line.equals(""))
{
System.out.println(line);
line = bis.readLine();
}
bos.write("Hello from java TCP Server!".getBytes());
} catch (IOException ex) {
System.out.println("Error in connnection: " + ex.getMessage());
}
}
Any help appreciated.
Web browsers require that the server speaks HTTP protocol. A proper server response would be:
BufferedOutputStream bos = new BufferedOutputStream(System.out);
byte[] message="Hello from java TCP Server!".getBytes();
bos.write("HTTP/1.1 200 OK\r\n".getBytes());
bos.write("Content-Type: text/plain\r\n".getBytes());
bos.write(("Content-Length: "+message.length+"\r\n").getBytes());
bos.write("\r\n".getBytes()); // empty line between HTTP header and HTTP content
bos.write(message);
You may test your program with another tool that speaks plain TCP sockets. Ich recommend "Netcat" (command: nc). Download for Windows: http://stefanfrings.de/avr_tools/netcat-win32-1.12.zip
Related
This is the first time I am not able to find the problem/bug in my code so now I am asking stackoverflow xD
I am currently learning how to write a simple Server - Client network to understand how Sockets and Server Sockets in Java work. Therefore, I wrote a "program" consisting of a Server, Client and Handler class. The Handler class is responsible for receiving the Client's messages and sending a response. Sending from Server to Client works perfectly fine, the Client receives the message. However, when the Client sends a message to the Server, it does not receive anything. The BufferedReader I am using is stuck on the readLine() request.
//This is the broken down version of what is happening in my Handler class
ServerSocket server = new ServerSocket(port); //These two lines of code actually happen in the Server class
Socket client = server.accept(); //but to simplify it I put them here
//Setting up the IO
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
//The Handler is waiting for the Reader to be ready and then prints the input
//Additionally, it sends a confirmation to the client
while(true) {
String input;
if(in.ready()){
if ((input = in.readLine()) != null) {
System.out.println(input);
out.println("Message Received");
if(input=="close") break;
}
}
}
//Expected output: "Message Received"
//Actual ouput: none, it gets stuck at in.ready() or in.readLine()
When I send a message from the Client it should just print the message and send a confirmation to the client but instead it either never gets past the if(in.ready()){...} part or gets stuck at if((input=in.readLine())!=null){...} if I remove the first if-statement. I used IntelliJ to debug it and the InputStream doesn't contain any message or the carriage return which is expected by readLine(). I find that to be really weird as the sending and receiving part of both the Server as well as the Client class is (mostly) the same.
The only thing I could think of that would maybe be the cause of this problem is that the Client somehow has problems sending the message.
//This is the broken down version of what is happening in my Client class
Socket client = new Socket();
client.connect(new InetSocketAddress("localhost",port));
//Setting up the IO
Scanner scanner = new Scanner(System.in); //I am using a Scanner for the message inputs
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
String input;
System.out.println("Enter the first Message: ");
while ((input = scanner.nextLine()) != null) {
String inServer;
System.out.println(input); //The input is correct
out.println(input); //I am suspecting it has something to do with this line or the PrintWriter
//This part works perfectly fine here while it does not in the Handler class
if (in.ready()) {
if ((inServer = in.readLine()) != null) {
System.out.println(inServer);
}
}
System.out.println("Enter next Message: ");
}
Expected output: inServer
Actual output: inServer
As you can see, the general setup of this part is the same as in the Handler class, yet something seems to go wrong when sending to the Server. I don't know if it is the Server (I don't think so because the same code for receiving messages works just fine in the Client class) or the Client, where in that case it would have to be a problem with the PrintWriter or something like that.
I have already looked at other/ similar questions here on stackoverflow but didn't find anything that would solve my problem.
The full code for the classes if someone wants to replicate everything in detail: (Pastebin links)
Server class
Client class
Handler class
Well, it seems the question has been answered...
It seems like it had something to do with the IntelliJ project the code was in. I had to move it into a new project and now it works.
The issue is resolved now and if someone wants to use this code as a base for a Server-Client system, I'll leave the pastebin-links working.
My suggestion is that you use read() method of the classes that implement Reader (BufferedReader is one of them). The syntax would be like this :
String data = "";
int i;
while ((i = in.read()) != -1){
data += (char)i;
}
This way is a lot more reliable and does not have the carriage return problem.
UPDATE:
I noticed that it works fine on a Windows machine, but it fails on Mac.
I created a basic Java Server code for socket connection. It runs on AWS Linux AMI, and I make a client connection from my computer. It works fine for first 4-5 answers from the client. However, after 4th or 5th answer, I don't get any response from the server and it just hangs. After a while, it gives SocketTimeout Exception.
I set socket timeout with setSoTimeout() in both side, and it didn't change anything. I wonder if it has anything to do with Amazon.
Client Code:
public static void main(String[] args) {
final int portNumber = 9090;
String connected = "1";
System.out.println(WELCOME);
try {
Socket socket = new Socket("ip", portNumber);
socket.setSoTimeout(0);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader input = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
out.println(connected);
while (connected.equals("1")) {
//read in situation
String situation = readInSituation(socket, input).replace(DELIMETER, "\n");
System.out.println(situation);
//send option
Scanner in = new Scanner(System.in);
System.out.print("Enter option: ");
out.println(in.nextLine());
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static String readInSituation(Socket socket, BufferedReader input) throws Exception {
while (!input.ready()) {
Thread.sleep(200);
}
return input.readLine();
}
Server Code is more complicated, but all it does is to respond to commands and print basic text on the screen.
Thanks
Don't use PrintWriter over the network, as it swallows exceptions, most probably a prior 'connection reset'. Use BufferedWriter. NB The ready() loop is literally a waste of time.
I have an Eclipse plugin that needs to open a pair of sockets to a flash application running on the local machine. Flash requires a policy file (blob of XML) giving permissions to access the ports in question. Flash prefers to get this policy file over port 843, Java treats ports < 1024 as privileged ports and Mac OS X and Linux similarly restrict access to ports < 1024. I don't want to run my Eclipse plugin with root permissions, so serving up the policy file on port 843 is not an option. According to Adobe documentation, if Flash can't get the policy file on port 843, it falls back to requesting the policy file on the port to which it's trying to connect. The ActionScript code looks like this:
/**
* Connecting to some port to communicate with the debugger. We initiate the
* connection because Flex doesn't allow us to listen to any ports.
*/
private function initSockets():void
{
requestSocket = new Socket();
requestSocket.addEventListener(Event.CONNECT, requestConnected);
requestSocket.addEventListener(Event.CLOSE, closed);
requestSocket.addEventListener(ProgressEvent.SOCKET_DATA, processRequestData);
requestSocket.addEventListener(IOErrorEvent.IO_ERROR, ioError);
requestSocket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityError);
requestSocket.connect("localhost", SCConstants.DEBUG_LESSON_REQUEST_PORT);
eventSocket = new Socket();
eventSocket.addEventListener(Event.CONNECT, eventConnected);
eventSocket.addEventListener(Event.CLOSE, closed);
eventSocket.addEventListener(ProgressEvent.SOCKET_DATA, processEventData);
eventSocket.addEventListener(IOErrorEvent.IO_ERROR, ioError);
eventSocket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityError);
eventSocket.connect("localhost", SCConstants.DEBUG_LESSON_EVENT_PORT);
}
On the Eclipse plugin side I've inherited some code that works most of the time on OS X, but sometimes fails on Windows. Running on Wi-Fi rather than wired ethernet also tends to fail, although I have no idea why this should matter.
public Boolean connect() throws DebugException {
try {
try {
// connection code
fRequestServerSocket = new ServerSocket(requestPort);
fRequestServerSocket.setSoTimeout(ACCEPT_TIMEOUT);
fEventServerSocket = new ServerSocket(eventPort);
fEventServerSocket.setSoTimeout(ACCEPT_TIMEOUT);
TWBLogger.logInfo("Open socket request server:" + fRequestServerSocket);
TWBLogger.logInfo("Open socket event server:" + fEventServerSocket);
String policy = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<cross-domain-policy>\n" +
"<allow-access-from domain=\"*\" to-ports=\"5000,5001\" secure=\"false\" />\n" +
"</cross-domain-policy>\0";
// Because of the Flash security policy the first thing
// that will accept on the socket will be the Flash Player
// trying to verify us. The Flash player will request security
// policy file with the following string: <policy-file-request/>\0
// We will serve back the above policy file and then close the socket
// The next thing to accept is our process in the VM.
fRequestSocket = fRequestServerSocket.accept();
fRequestWriter = new PrintWriter(fRequestSocket.getOutputStream());
fRequestReader = new BufferedReader(new InputStreamReader(fRequestSocket.getInputStream()));
// Wait some time before giving flash the policy file. Otherwise they don't get it. ;(
// 3 is too much ... ;(
Thread.sleep(100);
fRequestWriter.print(policy);
fRequestWriter.flush();
fRequestSocket.close();
// this should be the real connection
fRequestSocket = fRequestServerSocket.accept();
TWBLogger.logInfo("Open socket request:" + fRequestSocket);
fRequestWriter = new PrintWriter(fRequestSocket.getOutputStream());
fRequestReader = new BufferedReader(new InputStreamReader(fRequestSocket.getInputStream()));
// the same situation for the EventSocket
fEventSocket = fEventServerSocket.accept();
fEventReader = new BufferedReader(new InputStreamReader(fEventSocket.getInputStream()));
TWBLogger.logInfo("Open socket event:" + fEventSocket);
} catch (SocketTimeoutException e) {
TWBLogger.logWaring("Connection to the Client Timed out.");
cleanSockets();
return false;
requestFailed("Connection to the VM timed out. Please close any other running lessons that you debug and try again", e);
} catch (SocketSecurityException e) {
requestFailed("Security error occured when connecting to the VM", e);
} catch (Exception e) {
if (!fTerminated)
requestFailed("Error occured when connecting to the VM. Please close any other running lessons that you debug.", e);
}
} catch (DebugException e) {
// close the sockets so that we can debug another application
cleanSockets();
throw e;
}
// our VM is single threaded
fThread = new TWBThread(this);
fThreads = new IThread[] {fThread};
// start listening for events from the VM
fEventDispatch = new EventDispatchJob();
fEventDispatch.schedule();
// start listening for breakpoints
IBreakpointManager breakpointManager = getBreakpointManager();
breakpointManager.addBreakpointListener(this);
breakpointManager.addBreakpointManagerListener(this);
return true;
}
This code looks wrong. It doesn't wait for the message from Flash and instead just jams the policy response into the port. As I said, it works most of the time, but it fails sometimes and doesn't seem to comply with Adobe's documentation.
I tried listening for request packets on each port and sending a port specific response. I watched socket traffic using WireShark on the loopback interface (Mac OS X). I saw policy requests coming in and responses getting sent, but Flash still gave me Security Sandbox Violation on both ports.
I also tried adding this line at the beginning of initSockets shown above:
Security.loadPolicyFile("xmlsocket://localhost:5002");
Then I added code in my plugin to listen on port 5002 and send the following master policy file content:
private final static String FLASH_POLICY_RESPONSE =
"<?xml version=\"1.0\"?>\n" +
"<!DOCTYPE cross-domain-policy SYSTEM \"/xml/dtds/cross-domain-policy.dtd\">\n" +
"<cross-domain-policy>\n" +
"<site-control permitted-cross-domain-policies=\"master-only\"/>\n" +
"<allow-access-from domain=\"*\" to-ports=\"5000,5001\"/>\n" +
"</cross-domain-policy>\0";
Again I saw the request come in and the response go out, but Flash didn't seem to respond to it. I didn't get the Security Sandbox Violation errors, but there was also no traffic over the ports.
Can anyone enlighten me on the correct approach to opening sockets between Java and Flash?
I found the solution to this. I made a mistake early on and used BufferedReader.readLine to read the policy request. This isn't appropriate since policy requests are null terminated, not new line terminated. This was confusing since it does return when the underlying stream closes. Thus I got the request and sent a response, but the response was sent after the ActionScript code had already decided that the request had failed.
On the Java side I used the following code to establish communication on the ports:
// Create server sockets.
fRequestServerSocket = new ServerSocket(REQUEST_PORT);
fRequestServerSocket.setSoTimeout(ACCEPT_TIMEOUT);
TWBLogger.logInfo("Open socket request server:" + fRequestServerSocket);
fEventServerSocket = new ServerSocket(EVENT_PORT);
fEventServerSocket.setSoTimeout(ACCEPT_TIMEOUT);
TWBLogger.logInfo("Open socket event server:" + fEventServerSocket);
// Serve up the Flash policy file.
serveFlashPolicy();
// Connect request socket.
fRequestSocket = fRequestServerSocket.accept();
TWBLogger.logInfo("Open socket request:" + fRequestSocket);
fRequestWriter = new PrintWriter(fRequestSocket.getOutputStream());
fRequestReader = new BufferedReader(new InputStreamReader(fRequestSocket.getInputStream()));
// Connect event socket.
fEventSocket = fEventServerSocket.accept();
TWBLogger.logInfo("Open socket event:" + fEventSocket);
fEventReader = new BufferedReader(new InputStreamReader(fEventSocket.getInputStream()));
Serving up the policy file is handled as follows:
private void serveFlashPolicy() {
ServerSocket serverSocket = null;
Socket socket = null;
TWBLogger.logInfo("Waiting for flash policy request on port " + FLASH_POLICY_PORT);
try {
serverSocket = new ServerSocket(FLASH_POLICY_PORT);
serverSocket.setSoTimeout(ACCEPT_TIMEOUT);
socket = serverSocket.accept();
PrintWriter writer = new PrintWriter(socket.getOutputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
StringBuilder request = new StringBuilder();
int c;
while (0 < (c = reader.read())) {
request.append((char) c);
}
String policyRequest = request.toString();
if (policyRequest.startsWith(FLASH_POLICY_REQUEST)) {
writer.print(FLASH_POLICY_RESPONSE);
writer.print("\0");
writer.flush();
}
} catch (IOException e) {
TWBLogger.logWaring("IOException on port " + FLASH_POLICY_PORT + ": " + e.toString());
e.printStackTrace();
} finally {
if (null != socket) {
try {
socket.close();
} catch (Exception e) {
// Ignore
}
}
if (null != serverSocket) {
try {
serverSocket.close();
} catch (Exception e) {
// Ignore
}
}
}
TWBLogger.logInfo("Flash policy complete on port " + FLASH_POLICY_PORT);
}
The Flash policy response looks like this:
private final static String FLASH_POLICY_RESPONSE =
"<?xml version=\"1.0\"?>\n" +
"<!DOCTYPE cross-domain-policy SYSTEM \"/xml/dtds/cross-domain-policy.dtd\">\n" +
"<cross-domain-policy>\n" +
"<allow-access-from domain=\"*\" to-ports=\"5000,5001\"/>\n" +
"</cross-domain-policy>";
The site-control tag I had previously been sending is only allowed in master policy files served from port 843.
I attempted to create a PHP script which determines if the server (the computer which hosts the java program listed below) is running or not, If it is, the php funciton should return true, if not it returns false.
Here is the server:
package darestium.minecraft.server;
import java.io.BufferedReader;
import java.net.*;
import java.io.*;
public class Server {
private static ServerSocket socket;
private static Socket connection;
private static String command = new String();
private static String responseStr = new String();;
private static int port = 4343;
public static void main(String args[]) {
System.out.println("Signal Server is running.");
try {
socket = new ServerSocket(port);
while (true) {
connection = socket.accept();
InputStreamReader inputStream = new InputStreamReader(connection.getInputStream());
DataOutputStream response = new DataOutputStream(connection.getOutputStream());
BufferedReader input = new BufferedReader(inputStream);
command = input.readLine();
response.writeBytes(responseStr);
response.flush();
//response.close();
System.out.println("Running");
}
} catch (IOException e) {
System.out.println("Fail!: " + e.toString());
}
System.out.println("Closing...");
}
}
And here is the client:
<?
function isRunning() {
$address = 'darestium.dyndns-free.com';
$port = 4343;
$socket = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp'));
$message = 'loolololol';
try {
socket_connect($socket, $address, $port);
$status = socket_sendto($socket, $message, strlen($message), MSG_EOF, $address, $port);
if ($status != false) {
return true;
}
return false;
} catch (Exception $e) {
return false;
}
}
?>
The following are the error messages that show up on the php page that echos out the result of the function like so:
include('server.php');
echo isRunning();
Then the error messages:
Warning: socket_connect() [function.socket-connect]: unable to connect [0]: No connection could be made because the target machine actively refused it. in C:\Users\darestium\Documents\Portables\xampp\htdocs\darestium\minecraftserver.php on line 9
Notice: Use of undefined constant MSG_EOF - assumed 'MSG_EOF' in C:\Users\darestium\Documents\Portables\xampp\htdocs\darestium\minecraftserver.php on line 11
Warning: socket_sendto() expects parameter 4 to be long, string given in C:\Users\darestium\Documents\Portables\xampp\htdocs\darestium\minecraftserver.php on line 11
I was wondering how I could fix this issue. Also, I would like to be able to send messages to the server, any ideas how I could do this? I am basing this off Simple Java TCP Server and PHP Client Problems
Note: that I am very new to Sockets, and Server/Client communication.
Edit:
#VideanuAdrian OK, just port forwarded the port 4343 and it no longer shows up with the first error, but the function always seems to return false, and the last two errors still show.
You should not close the DataOutputStream object in your server.
Just comment the line response.close(); in your server and the program should work.
When running a Client/Server you need to know if the user that runs the app has access to the port. Ports to 1024 are reserved by the system know apps/services. That´s point 1.
Point 2: One of the best ways is to run the server inside a connection-thread approach. Running in this way, when a new client request arrives, the server can delegate the request handle to the connection thread.
Point 3: The message is related to the protocol. If you are using a built protocol like HTTP or FTP, you must use the protocol rules. If not, you could built your own rules for the message request/response.
I recomend you to read the Java Networking Tutorial before continue. Run all Java examples. Later, you could mix with PHP. The more information about sockets and protocols you have, the better your programm will be.
http://docs.oracle.com/javase/tutorial/networking/
Hope this can help you.
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.