Soy nuevo en Scala, por lo que la pregunta puede ser bastante simple, aunque he dedicado un tiempo a intentar resolverla. Tengo un simple servidor TCP Scala (sin actores, hilo sencillo):Problemas con el socket en el simple servidor TCP de Scala
import java.io._
import java.net._
object Application {
def readSocket(socket: Socket): String = {
val bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream))
var request = ""
var line = ""
do {
line = bufferedReader.readLine()
if (line == null) {
println("Stream terminated")
return request
}
request += line + "\n"
} while (line != "")
request
}
def writeSocket(socket: Socket, string: String) {
val out: PrintWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream))
out.println(string)
out.flush()
}
def main(args: Array[String]) {
val port = 8000
val serverSocket = new ServerSocket(port)
while (true) {
val socket = serverSocket.accept()
readSocket(socket)
writeSocket(socket, "HTTP/1.1 200 OK\r\n\r\nOK")
socket.close()
}
}
}
El servidor escucha en localhost:8000
para solicitudes incomming y envía la respuesta HTTP con un solo OK
palabra en el cuerpo. Luego ejecuto Apache Benchmark de esta manera:
ab -c 1000 -n 10000 http://localhost:8000/
que funciona muy bien por primera vez. La segunda vez que se inicia ab
se cuelga producir la siguiente salida en netstat -a | grep 8000
:
....
tcp 0 0 localhost.localdo:43709 localhost.localdom:8000 FIN_WAIT2
tcp 0 0 localhost.localdo:43711 localhost.localdom:8000 FIN_WAIT2
tcp 0 0 localhost.localdo:43717 localhost.localdom:8000 FIN_WAIT2
tcp 0 0 localhost.localdo:43777 localhost.localdom:8000 FIN_WAIT2
tcp 0 0 localhost.localdo:43722 localhost.localdom:8000 FIN_WAIT2
tcp 0 0 localhost.localdo:43725 localhost.localdom:8000 FIN_WAIT2
tcp6 0 0 [::]:8000 [::]:* LISTEN
tcp6 83 0 localhost.localdom:8000 localhost.localdo:43724 CLOSE_WAIT
tcp6 83 0 localhost.localdom:8000 localhost.localdo:43786 CLOSE_WAIT
tcp6 1 0 localhost.localdom:8000 localhost.localdo:43679 CLOSE_WAIT
tcp6 83 0 localhost.localdom:8000 localhost.localdo:43735 CLOSE_WAIT
tcp6 83 0 localhost.localdom:8000 localhost.localdo:43757 CLOSE_WAIT
tcp6 83 0 localhost.localdom:8000 localhost.localdo:43754 CLOSE_WAIT
tcp6 83 0 localhost.localdom:8000 localhost.localdo:43723 CLOSE_WAIT
....
Dado que no más peticiones son atendidas por el servidor. Un detalle más: el mismo script ab
con los mismos parámetros funciona sin problemas probando un servidor Node.js simple en la misma máquina. Por lo que este problema no está relacionado con una serie de conexiones TCP abiertas que he puesto para ser reutilizable con
sudo sysctl -w net.ipv4.tcp_tw_recycle=1
sudo sysctl -w net.ipv4.tcp_tw_reuse=1
Podría alguien darme una pista sobre lo que me falta?
Editar: Terminación de la corriente de manipulación se ha añadido al código anterior:
if (line == null) {
println("Stream terminated")
return request
}
CLOSE_WAIT significa que TCP está esperando a que la aplicación para cerrar su zócalo. Otro problema es que no está enviando los terminadores de línea correctos para HTTP. Se especifican como \ r \ n, no \ n. – EJP
He actualizado el código a '\ r \ n' aunque' curl' y 'ab' parecen funcionar bien con' \ n'. En cuanto a CLOSE_WAIT, no parece ser la raíz del problema. Gracias por comentar – nab
CLOSE_WAIT es un síntoma del problema de que la aplicación no ha cerrado el socket. – EJP