Java套接字服务器,PHP套接字客户端;通信有效,但是 PHP 仅在套接字连接关闭后“回显”数据


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

我正在尝试在基于 Java 的套接字服务器和基于 PHP 的套接字

客户端之间创建一个简单的基于套接字的服务器/客户端通信。我按预期收到了所有回复,但不是立即收到。这是我正在尝试做的.PHP客户端向 Java 服务器发送命令,它会回复答案。此答案应立即显示在 PHP 页面上。然后发送第二个命令,服务器再次发送应立即显示的响应。但是,就我而言,只有在整个基于套接字的通信终止后,响应才会被"回显"。那是在我关闭来自 PHP 客户端的套接字连接之后。

以下是我的 Java 套接字服务器代码:

    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();
            }
        }
    }

以下是我的示例 PHP 客户端源代码:

<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>

在这种情况下,整个 PHP 输出显示在末尾。我什至尝试在不同的地方放置睡眠,但是在写入输出之前,它似乎正在等待套接字连接关闭。我怎样才能获得输出"实时"。像正常的聊天交流一样?我在这里做错了什么?

您的脚本运行良好,并且对于您要查找的内容没有太大缺陷。由于从命令行而不是 Web 浏览器运行脚本时会获得所需的结果,因此我们可以查明问题的原因:HTTP 协议

HTTP不是为持续连接而生的(就像你习惯的Java套接字一样),但它简化的工作流程是基于请求/精心设计/响应/忘记的路线。因此,您不能通过HTTP解决方案与纯HTML/PHP进行"实时聊天"。

唉,并不是你所有的希望都失去了!要实现"实时"通信,您可以使用Ajax,这并不难习惯。我说"实时"是因为它仍然是一个基于 HTTP 的解决方案,但至少你可以从同一个网页内发出请求并接收响应,这是你最接近 HTML/PHP/AJAX 三元组

的。

看来你不太了解 http 的 php。只有在 php 客户端代码完成执行后,您才会获得 HTML 响应。(即)您的所有回声都将放置在您指定的位置并作为一个整体返回。进入睡眠状态只会延迟执行。