我有一个非常基本的多线程Web服务器的启动,它可以接收所有GET请求,只要它们一次来一个。
然而,当多个GET请求同时进入时,有时它们都会被收到,有时则会丢失一些。
我通过创建一个html页面来测试这一点,该页面包含指向我的网络服务器并在firefox中打开页面的多个图像标记。我总是使用shift + refresh。
这是我的代码,我必须做一些根本错误的事情。
public final class WebServer
{
public static void main(String argv[]) throws Exception
{
int port = 6789;
ServerSocket serverSocket = null;
try
{
serverSocket = new ServerSocket(port);
}
catch(IOException e)
{
System.err.println("Could not listen on port: " + port);
System.exit(1);
}
while(true)
{
try
{
Socket clientSocket = serverSocket.accept();
new Thread(new ServerThread(clientSocket)).start();
}
catch(IOException e)
{
}
}
}
}
public class ServerThread implements Runnable
{
static Socket clientSocket = null;
public ServerThread(Socket clientSocket)
{
this.clientSocket = clientSocket;
}
public void run()
{
String headerline = null;
DataOutputStream out = null;
BufferedReader in = null;
int i;
try
{
out = new DataOutputStream(clientSocket.getOutputStream());
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
while((headerline = in.readLine()).length() != 0)
{
System.out.println(headerline);
}
}
catch(Exception e)
{
}
}
答案 0 :(得分:3)
首先,@ skaffman的评论是现货。您不应该像代码当前那样捕获并忽略异常。总的来说,这是一种可怕的做法。在这种情况下,你很可能会丢掉可以告诉你真正问题是什么的证据。
其次,我认为您可能会误解服务器的功能。无论您如何实现它,服务器每秒只能处理一定数量的请求。如果你向它发出的请求多于此,则必须删除一些请求。
我怀疑发生的事情是您在短时间内发送了太多请求,并且压倒了操作系统的请求缓冲区。
当您的代码绑定到服务器套接字时,操作系统会设置一个请求队列来保存绑定的IP地址/端口上的传入请求。此队列具有有限大小,如果在新请求到来时队列已满,则操作系统将丢弃请求。这意味着,如果您的应用程序无法足够快地accept
请求,则会删除一些请求。
你能做些什么?
ServerSocket.bind(...)
的重载,允许您指定要在OS级别队列中保留的backlog
个请求。您可以使用此...或使用更大的待办事项。<强> CAVEATS 强>
你需要小心一点。很可能您可以修改您的应用程序以在短期内接受(而不是删除)更多请求。但从长远来看,您应该只接受请求,就像您实际处理它们一样快。如果它比你处理它们更快地接受它们,那么可能会发生许多不好的事情:
为了防止这种情况,实际上最好不要急切地接受尽可能多的请求。相反,使用有界线程池,并调整池大小(等)以优化吞吐率,同时保持在合理限制内处理单个请求的时间。
答案 1 :(得分:2)
我实际上发现问题是这样的:
static Socket clientSocket = null;
一旦我移除静电,它现在可以很好地工作。