无法再次接受TcpClient C#

时间:2012-04-24 21:04:43

标签: c# ftp tcpclient tcpserver

我是C#和客户端 - 服务器编程的新手。现在,对于课程,我正在尝试创建一个FTP客户端,而不使用任何预先建立的FTP库。我觉得我的项目大部分时间都处于停机状态,但是当我进行多次调用需要使用数据端口(list,retr等)时,我遇到了问题。这是一个代码示例那是打破:

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是一种获取网络流并在.5秒超时内打印出所有可用内容的方法,stream是当前连接到FTP服务器的NetworkStream,而writer是同一网络流,包含在StreamReader中以方便将ASCII字符写入服务器。如果您想知道为什么我使用流阅读器从数据连接中读取,那是因为服务器在传输数据后关闭了连接,因此我可以轻松获得eof通知。当我使用封闭的网络流时,我的GetServerMessage方法因某种原因而中断。

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

这个代码在我第一次运行它时会执行没有缺陷但是如果我再次尝试它,它会挂起'tmpclient = tmpserver.AcceptTcpClient();'线。它永远不会达到“无处”的印刷声明。我相信这是因为我在同一个端口上从同一台机器接收客户端,但我不确定。我尝试添加一个布尔值,以确保AcceptTcpClient()只运行一次,但后来我遇到了运行时错误,视觉工作室告诉我,我可能已经'在我完成它之前释放了资源'我预测这将是一个问题但是如何判断服务器在关闭连接后是否重新建立连接?

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

如果我一点都不清楚,我道歉,但是我对这个问题缺乏了解,这使我难以表达我的问题。如果对问题是什么感到困惑,我会很乐意尝试清除它。

3 个答案:

答案 0 :(得分:3)

为了能够接受另一个客户端,您应该执行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();
    }
}

答案 1 :(得分:0)

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

答案 2 :(得分:0)

关闭tcp客户端流后,您将无法再读取从中提取的流。

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

客户端必须请求另一个连接,

OR

您应该保持tcp客户端套接字打开。

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