简体   繁体   中英

Socket programming exercise hanging?

I've created a very simple HTTP proxy server and backend server that generates simple requests.

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

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()使其工作。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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