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.