第二次无法接受TcpClient C#

问题描述:

我是C#和客户端 - 服务器编程的新手。现在,对于课堂,我试图创建一个FTP客户端,而不使用任何预先建立的FTP库。我觉得我的项目大部分时间都没有完成,但是当我做了多个需要使用数据端口的调用时(例如list,retr等),我遇到了一个问题。下面是代码示例那是打破:第二次无法接受TcpClient C#

writer.WriteLine(portcmd); 
writer.Flush(); 

GetServerMessage(stream); 

writer.WriteLine("list "); 
writer.Flush(); 


tmpserver = new TcpListener(IPAddress.Any, 3128); 
tmpserver.Start(); 
tmpclient = tmpserver.AcceptTcpClient(); 
Console.WriteLine("gothere"); 

if (!tmpclient.Connected) 
{ 
    tmpserver.Start(); 
} 

StreamReader tmpreader = new StreamReader(tmpclient.GetStream()); 

GetServerMessage(stream); 
while (tmpreader.Peek() != -1) 
{ 
    Console.WriteLine(tmpreader.ReadLine()); 
} 

tmpclient.Close(); 
tmpserver.Stop(); 

GetServerMessage(stream); 

Getservermessage是需要一个网络数据流,并打印出一个0.5秒的超时内一切可用的方法,流是的NetworkStream当前连接到FTP服务器,和作家是相同的包装在StreamReader中的网络流,便于将ASCII字符写入服务器。如果您想知道为什么我使用流读取器从数据连接中读取数据,那是因为服务器在传输数据后关闭了连接,因此我可以轻松获得eof通知。我使用封闭的网络流时,我的GetServerMessage方法出于某种原因中断了。

此代码正在向FTP服务器发送端口命令以通知它我将要求数据连接(前两行)然后发送list命令,建立与服务器的数据连接,获取所需的信息,然后终止数据连接(代码的其余部分)。

这段代码在第一次运行时会没有任何缺陷地执行,但如果再次尝试,它会挂在'tmpclient = tmpserver.AcceptTcpClient();'线。它从来没有达到“gothere”打印声明。我相信这是因为我在同一个端口上从同一台机器接收客户端,但我不确定。我尝试添加一个布尔值以确保AcceptTcpClient()只运行一次,但后来出现运行时错误,Visual Studio告诉我可能在我完成之前释放了资源。“我预测这会是一个问题,但是,我怎么知道服务器在关闭一次后是否重新建立连接?

在给定的代码结束时,我停止tmpserver并关闭tmpclient。我原来是这样做的,因为我知道FTP服务器在完成传输时会关闭连接,并认为这是正确的做法。我发现如果我注释掉这些代码,代码将会执行多次,但流显示为空...我不确定这些信息是否有用,但我想我会提及它。

我很抱歉,如果我一点都不清楚,但是我对这个问题的知识缺乏使我很难阐明我的问题。如果对这个问题有什么困惑,我会很乐意尝试清除它。

为了能够接受另一个客户端,您应该执行tmpclient = tmpserver.AcceptTcpClient();,并等待第一个客户端(接受第二客户端之前)完成其作品可能不是一个好主意

这里是等待一个示例服务器代码连接和回声从每个客户端发送的字符串。你可以用telnet localhost 3128

Thread t = new Thread(Server); 
t.IsBackground = true; 
t.Start(); 

测试 -

void Server() 
{ 
    TcpListener listener = new TcpListener(IPAddress.Any, 3128); 
    listener.Start(); 
    while (true) 
    { 
     var client = listener.AcceptTcpClient(); 
     new Thread(() => 
     { 
      using (client) 
      { 
       var reader = new StreamReader(client.GetStream()); 
       var writer = new StreamWriter(client.GetStream()); 
       while (true) 
       { 
        string line = reader.ReadLine(); 
        if (line == "QUIT") break; 
        writer.WriteLine("From Thread[" + Thread.CurrentThread.ManagedThreadId + "] > " + line); 
        writer.Flush(); 
       } 
      } 
     }).Start(); 
    } 
} 
+0

有了改变我的代码工作的一点点,这似乎已经解决了我的问题,所以谢谢!我正在从FTP服务器收到另一个错误,现在声明“425无法建立数据连接:地址已在使用中” – Tom 2012-04-25 01:13:55

好的,就是这样。要以简单的方式执行服务器,您需要脱离处理客户端套接字的代码。当accept返回时,创建并启动一个线程,将其传递给'tmpclient',然后再次循环到accept调用,以便任何新客户端都可以连接。在新产生的服务器客户端线程中,读取并写入循环中传递的套接字以与客户端进行通信。

一旦你关闭你的tcp客户端流,你就不能再从你从它那里读取的流中读取数据。

var stream = tcpClient.GetStream(); 
... 
tcpclient.Close(); 
... 
stream.Read .. fail 

客户将不得不请求另一个连接,

OR

您应该保留TCP客户端套接字打开。

更复杂的服务器会保留一些关于客户端的元数据(状态),所以当套接字意外关闭时 - 并且客户端很快尝试重新连接时,服务器可以继续顺利地进行处理。