简体   繁体   English

socket编程练习挂了?

[英]Socket programming exercise hanging?

I've created a very simple HTTP proxy server and backend server that generates simple requests.我创建了一个非常简单的 HTTP 代理服务器和后端服务器,可以生成简单的请求。

Proxy Server代理服务器

package ch2.networking

import java.io.{BufferedReader, InputStreamReader}
import java.net.{ServerSocket, Socket}

class ProxyServer(address: String, port: Int, proxyPort: Int) {
  val proxySocket = new ServerSocket(proxyPort)

  while (true) {
    println("Proxy accepting connections...")
    val connectionSocket = proxySocket.accept()
    println(s"Proxy Accepted Connection: $connectionSocket")

    val connectionInputStream = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream))

    val serverSocket = new Socket(address, port)
    val serverInputStream = new BufferedReader(new InputStreamReader(serverSocket.getInputStream))

    val message: String = connectionInputStream.readLine()
    println(s"Proxy server received: $message")
    serverSocket.getOutputStream.write(message.getBytes("UTF-8"))

    val response = serverInputStream.readLine()
    println(s"Proxy server received $response from server")
    connectionSocket.getOutputStream.write(response.getBytes("UTF-8"))
  }
}

Web Server网络服务器

package ch2.networking

import java.io.{BufferedReader, InputStreamReader}
import java.net.ServerSocket

class Server(port: Int) {
  val socket = new ServerSocket(port)

  while (true) {
    println("Server accepting connections...")
    val connectionSocket = socket.accept()
    println(s"Server Accepted Connection: $connectionSocket")
    val inputStream = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream))
    val request = inputStream.readLine()
    println(s"Received: $request")
    val response =
      """
        |HTTP/1.1 200 OK
        |
        |
        |Yay you win
        |""".stripMargin
    connectionSocket.getOutputStream.write(response.getBytes("UTF-8"))
  }
}

The proxy receives the message, but then the write to the web server hangs forever.代理收到消息,但随后对 Web 服务器的写入永远挂起。 What did I do wrong?我做错了什么?

Here's an implementation that works:这是一个有效的实现:

import java.io.InputStream
import java.net.{ServerSocket, Socket}

import scala.annotation.tailrec

trait InputReader {
  @tailrec
  final def readRecur(in: InputStream, sb: StringBuilder = new StringBuilder): String = {
    val input = in.read()
    if (input != -1) {
      readRecur(in, sb.append(input.toChar))
    } else sb.toString()
  }
}

class Server(port: Int) extends Thread with InputReader {
  val socket = new ServerSocket(port)
  override def run(): Unit = {
    while (true) {
      println("Server accepting connections...")
      val connectionSocket = socket.accept()
      println(s"Server Accepted Connection: $connectionSocket")

      val in = connectionSocket.getInputStream
      val message = readRecur(in)

      println(s"Received: $message")
      val response =
        """
          |HTTP/1.1 200 OK
          |
          |
          |Yay you win
          |""".stripMargin
      connectionSocket.getOutputStream.write(response.getBytes("UTF-8"))
      connectionSocket.shutdownOutput()
    }
  }
}

class ProxyServer(address: String, port: Int, proxyPort: Int)
    extends Thread
    with InputReader {
  val proxySocket = new ServerSocket(proxyPort)

  override def run(): Unit = {
    while (true) {
      println("Proxy accepting connections...")
      val connectionSocket = proxySocket.accept()
      val connectionInputStream = connectionSocket.getInputStream
      println(s"Proxy Accepted Connection: $connectionSocket")

      val serverSocket = new Socket(address, port)
      val serverInputStream = serverSocket.getInputStream

      val message: String = readRecur(connectionInputStream)
      println(s"Proxy server received: $message")
      serverSocket.getOutputStream.write(message.getBytes("UTF-8"))
      serverSocket.shutdownOutput()

      val response = readRecur(serverInputStream)
      println(s"Proxy server received $response from server")
      connectionSocket.getOutputStream.write(response.getBytes("UTF-8"))
      connectionSocket.shutdownOutput()
    }
  }
}

object ProxyServer extends InputReader {
  def main(args: Array[String]): Unit = {
    val server = new Server(2222)
    println("starting server")
    server.start()

    val proxyServer = new ProxyServer("0.0.0.0", 2222, 3333)
    println("starting proxy server")
    proxyServer.start()

    // Begin testing
    val proxyServerSocket = new Socket("0.0.0.0", 2222)
    val message: String = "Hello!"
    println(s"Client sending message: $message")
    proxyServerSocket.getOutputStream.write(message.getBytes("UTF-8"))
    proxyServerSocket.shutdownOutput()

    val response = readRecur(proxyServerSocket.getInputStream)
    println(s"Client received: $response")

    server.stop()

  }
}

Apparently the trouble was with the read operation, they never knew when to stop expecting more.显然问题出在读取操作上,他们永远不知道什么时候停止期待更多。 Socket communication is pretty basic, the client and the server will have to agree on a protocol (something like http) to ensure they both understand each other.套接字通信是非常基本的,客户端和服务器必须就协议(如 http 之类的)达成一致,以确保它们相互理解。

In the above example I've created a pretty basic reader, that keeps reading until the communication is marked done from the other side.在上面的例子中,我创建了一个非常基本的阅读器,它会一直阅读,直到通信从另一端标记为完成。

在这种特殊情况下,您可以在编写服务器响应后添加connectionSocket.close()使其工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM