Java socket server, PHP socket client; communication works, however PHP 'echoes' data only after the socket connection is closed

StackOverflow https://stackoverflow.com/questions/22832700

I am trying to create a simple socket based server/client communication between a Java-based socket server and PHP-based socket client. I am getting all the responses as expected but not immediately. Here is what I am trying to do. PHP client sends a command to the Java server, it responds back with an answer. This answer should be displayed on PHP page immediately. Then a second command is sent and again, the server sends a response which should be displayed immediately. However in my case, the responses are 'echoed' only after entire socket based communication is terminated. That is after I close the socket connection from PHP client.

Following is my Java Socket Server code:

    public class MultiThreadServer implements Runnable {
        Socket csocket;

        MultiThreadServer(final Socket csocket) {
            this.csocket = csocket;
        }

        private static void download(final String url) {
            try {
                final URL downloadURL = new URL(url);
                URLConnection conn = null;
                try {
                    conn = downloadURL.openConnection();
                    final InputStream inputStream = conn.getInputStream();
                    final long filesize = conn.getContentLength();
                    System.out.println("Size of file : " + (filesize / 1024)
                            + " (kb)");
                    final FileOutputStream outputStream = new FileOutputStream(
                            System.getProperty("user.dir") + "/test.exe");
                    final long startTime = System.currentTimeMillis();
                    final byte[] buffer = new byte[1024];
                    int bytesRead = -1;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, bytesRead);
                    }
                    final long endTime = System.currentTimeMillis();
                    System.out.println("File downloaded");
                    System.out.println("Download time in sec. is : "
                            + ((endTime - startTime) / 1000));
                    outputStream.close();
                    inputStream.close();
                } catch (final IOException e) {
                    e.printStackTrace();
                }
            } catch (final MalformedURLException e) {
                e.printStackTrace();
            }
        }

        public static void main(final String args[]) throws Exception {
            final ServerSocket ssock = new ServerSocket(3333);
            System.out.println("Listening on " + ssock.toString());
            while (true) {
                final Socket sock = ssock.accept();
                System.out.println("Connected to " + sock.getRemoteSocketAddress());
                new Thread(new MultiThreadServer(sock)).start();
            }
        }

        @Override
        public void run() {
            try {
                final BufferedReader br = new BufferedReader(new InputStreamReader(
                        this.csocket.getInputStream()));
                final BufferedWriter bw = new BufferedWriter(
                        new OutputStreamWriter(this.csocket.getOutputStream()));
                bw.write(this.csocket.getRemoteSocketAddress().toString()
                        .replace("/", "")
                        + "\n");
                bw.flush();
                String line;
                while ((line = br.readLine()) != null) {
                    if (line.equalsIgnoreCase("getMacName")) {
                        final String macName = InetAddress.getLocalHost()
                                .getHostName();
                        bw.write(macName + "\n");
                        bw.flush();
                        System.out.println("Machine Name : " + macName);
                    } else if (line.equalsIgnoreCase("getMacIP")) {
                        final String macIP = InetAddress.getLocalHost()
                                .getHostAddress();
                        bw.write(macIP + "\n");
                        bw.flush();
                        System.out.println("Machine IP : " + macIP);
                    } else if (line.equalsIgnoreCase("getCurrentVersion")) {
                        final String currVersion = "0.1a";
                        bw.write(currVersion + "\n");
                        bw.flush();
                        System.out.println("Current Version : " + currVersion);
                    } else if (line
                            .equalsIgnoreCase("downUrl:http://webserver/webapp/test.exe")) {
                        final String url = line.substring(8);
                        bw.write("Downloading : " + url + "\n");
                        bw.flush();
                        MultiThreadServer.download(url);
                        System.out.println("URL : " + url);
                    } else if (line.equalsIgnoreCase("exit")) {
                        bw.write("Closing\n");
                        bw.flush(); 
                        bw.close();
                        br.close();
                        System.out.println("Exiting!");
                        this.csocket.close();
                        break;
                    }
                }
            } catch (final IOException e) {
                e.printStackTrace();
            }
        }
    }

Following is my sample PHP client source code:

<html>
<head>
<title>Socket Connection Test</title>
</head>
<body>
<h3>Testing Socket Connection</h3>
<br>
<?php
$host="127.0.0.1";
$port = 3333;
$fp;
$macName;
$macIP;
$message;
$result;

// open a client connection
$fp = fsockopen ($host, $port, $errno, $errstr);

if (!$fp)
{
$result = "Error: Could not open socket connection! Error No: " . $errno . ". Error String: " . $errstr;
die($result);
}
else
{
$message = fgets ($fp, 1024);
$message = trim($message);
echo "Connected to remote server on current port : " . $message;
echo "<br>";
sleep(5);

// get machine name
fwrite ($fp, "getMacName\n");
$macName = fgets ($fp, 1024);
$macName = trim($macName);
echo "Machine Name : " . $macName;
echo "<br>";
sleep(5);

// get IP address
fwrite ($fp, "getMacIP\n");
$macIP = fgets ($fp, 1024);
$macIP = trim($macIP);
echo "Machine IP : " . $macIP;
echo "<br>";
sleep(5);

fwrite ($fp, "getCurrentVersion\n");
$currVersion = fgets ($fp, 1024);
$currVersion = trim($currVersion);
echo "Current Version : " . $currVersion;
echo "<br>";
sleep(5);

fwrite ($fp, "downUrl:http://webserver/webapp/text.exe\n");
$downResponse = fgets ($fp, 1024);
$downResponse = trim($downResponse);
echo "Download Response : " . $downResponse;
echo "<br>";
sleep(5);

fwrite ($fp, "exit\n");
$exitStatus = fgets ($fp, 1024);
fclose ($fp);
echo "Connection Closed.";
}
?>
</body>
</html>

In this case, the entire PHP output is displayed at the end. I even tried putting sleeps at various places, however it seems to be waiting for socket connection to be closed before writing the output. How can I can I get the output "LIVE". Like a normal chat communication? What am I doing wrong here?

有帮助吗?

解决方案

Your script works okay, and has no big flaws for what you're looking for. Since you obtain the desired result when you run the script from command line rather than a web browser, we can pinpoint the cause of the issue: the HTTP protocol

HTTP isn't made for sustained connections (like you're used to with Java sockets) but it's simplified workflow is based along the lines of Request/Elaborate/Response/Forget. Therefore, you can't have a "live chat" with a pure HTML/PHP over HTTP solution.

Alas, not all your hopes are lost! To implement a "live" communication you can use Ajax, which isn't too hard to get used to. I've said "live" because it's still an HTTP based solution, but at least you can have requests and receive responses from within the same webpage, which is the closest you can get with the HTML/PHP/AJAX triad.

其他提示

It seems you dont understand php with http well . You will get the HTML response only after your php client code completes execution. (i.e) all your echo's will be put in place where you specified and returned as a whole. Putting sleep will only delay the execution.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top