题
我正在尝试创建一个简单的C#Web服务器,在此阶段,您可以通过浏览器访问,并且只会执行“Hello World”。
我遇到的问题是服务器可以很好地接收数据 - 我得到浏览器的标题信息 - 但浏览器没有收到我发送的任何内容。此外,我只能通过访问localhost(或127.0.0.1)连接到服务器。我无法通过访问我的IP来实现它并且它不是网络设置,因为如果我运行它,Apache工作正常。此外,我正在使用端口监视程序,在尝试从浏览器进行连接后,进程的端口卡在TIME_WAIT状态,即使我告诉连接关闭,它应该回到LISTEN。
这是相关代码。几个电话可能没有意义,但这是一个更大的节目。
class ConnectionHandler
{
private Server server;
private TcpListener tcp;
private ArrayList connections;
private bool listening;
private Thread listeningThread;
public Server getServer()
{
return server;
}
private void log(String s, bool e)
{
server.log("Connection Manager: " + s, e);
}
private void threadedListen()
{
while (listening)
{
try
{
TcpClient t = tcp.AcceptTcpClient();
Connection conn = new Connection(this, t);
}
catch (NullReferenceException)
{
log("unable to accept connections!", true);
}
}
log("Stopped listening", false);
}
public void listen()
{
log("Listening for new connections", false);
tcp.Start();
listening = true;
if (listeningThread != null && listeningThread.IsAlive)
{
listeningThread.Abort();
}
listeningThread = new Thread(new ThreadStart(
this.threadedListen));
listeningThread.Start();
}
public void stop()
{
listening = false;
if (listeningThread != null)
{
listeningThread.Abort();
log("Forced stop", false);
}
log("Stopped listening", false);
}
public ConnectionHandler(Server server)
{
this.server = server;
tcp = new TcpListener(new IPEndPoint(
IPAddress.Parse("127.0.0.1"), 80));
connections = new ArrayList();
}
}
class Connection
{
private Socket socket;
private TcpClient tcp;
private ConnectionHandler ch;
public Connection(ConnectionHandler ch, TcpClient t)
{
try
{
this.ch = ch;
this.tcp = t;
ch.getServer().log("new tcp connection to "
+ this.tcp.Client.RemoteEndPoint.ToString(), false);
NetworkStream ns = t.GetStream();
String responseString;
Byte[] response;
Int32 bytes;
responseString = String.Empty;
response = new Byte[512];
bytes = ns.Read(response, 0, response.Length);
responseString =
System.Text.Encoding.ASCII.GetString(response, 0, bytes);
ch.getServer().log("Received: " + responseString);
String msg = "<html>Hello World</html>";
String fullMsg = "HTTP/1.x 200 OK\r\n"
+ "Server: Test Server\r\n"
+ "Content-Type: text/html; "
+ "charset=UTF-8\r\n"
+ "Content-Length: " + msg.Length + "\r\n"
+ "Date: Sun, 10 Aug 2008 22:59:59 GMT"
+ "\r\n";
nsSend(fullMsg, ns);
nsSend(msg, ns);
ns.Close();
tcp.Close();
}
catch (ArgumentNullException e)
{
ch.getServer().log("connection error: argument null exception: " + e);
}
catch (SocketException e)
{
ch.getServer().log("connection error: socket exception: " + e);
}
}
private void nsSend(String s, NetworkStream ns)
{
Byte[] data = System.Text.Encoding.ASCII.GetBytes(s);
ns.Write(data, 0, data.Length);
ns.Flush();
ch.getServer().log("Sent: " + s);
}
}
有没有人有任何想法?我觉得这对我来说是愚蠢的,但我只是不知道是什么。我真的很感激任何见解
解决方案
您可能想知道可以使用 HttpListener
非常容易编写基本的Web服务器 - 这可以解决大部分痛苦的问题,让您专注于编写实际的代码。 MSDN页面给出了一个示例。
请注意,这使用HTTP.SYS,这很好 - 但意味着非管理员需要明确授予对开放端口的访问权限;在xp上,您可以使用 httpcfg
执行此操作;在Vista上,您可以使用 netsh
。参见此处了解更多信息。
其他提示
目前不存在问题但可能稍后的一件事是您的内容长度基于消息字符串的 Unicode 长度,而不是二进制文件长度。
在Connection构造函数中也有相当多的东西 - 根本不属于构造函数的东西,IMO。如果发生异常,它也不会关闭。
您是否看过像WireShark这样的网络跟踪器中发生了什么?这将是查看任何数据是否被发送回客户端的最简单方法。
或者,发布一个简短但完整的代码版本,我们可以自行编译和运行。
也许我只是遗漏了一些东西,但你只能在localhost上连接的原因是因为你正在监听的IP是127.0.0.1,这使得TCPListener只监听该IP地址。我没有看到你在任何地方调用任何客户端断开连接,TCPListener是一个阻塞调用,所以它一直存在,直到建立连接。在我以前使用TCP / IP和TCPListener,TCPClient类的经验中,没有太多方法可以强制侦听器在删除客户端连接之前删除它的连接。调用TCPListener.Abort()不会丢弃阻止端口阻塞的客户端连接。
对于想要从本地网络IP地址访问C#服务器的类似情况的任何人,您需要监听地址0.0.0.0意味着监听所有IP地址,而不是像127.0.0.1等特定的地址