我是Scala的新手,所以问题可能很简单,但我已经花了一些时间尝试解决它。我有一个简单的Scala TCP服务器(没有actors,单线程):
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()
}
}
}
服务器监听来自 localhost:8000
的请求,并在响应中发送一个带有单词 OK
的 HTTP 响应体。接着我像这样运行 Apache Benchmark:
ab -c 1000 -n 10000 http://localhost:8000/
第一次使用很顺利。第二次启动ab
时,它会挂起,并在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
....
由于服务器不再提供更多的请求。还有一个细节:使用相同参数的ab
脚本在同一台机器上测试简单的Node.js服务器时可以顺利运行。因此,这个问题与我设置为可重用的打开TCP连接的数量无关。
sudo sysctl -w net.ipv4.tcp_tw_recycle=1
sudo sysctl -w net.ipv4.tcp_tw_reuse=1
请问有谁能给我一些线索,告诉我我漏掉了什么?
编辑:已在上述代码中添加了流处理的终止。
if (line == null) {
println("Stream terminated")
return request
}
\r\n
,尽管curl
和ab
似乎都可以正常使用\n
。至于CLOSE_WAIT - 它似乎不是问题的根源。谢谢您的评论。 - nab