无法再次接受 TcpClient C#

本文关键字:TcpClient | 更新日期: 2023-09-27 18:32:05

我是C#和客户端-服务器编程的新手。现在,对于类,我正在尝试在不使用任何预先建立的FTP库的情况下创建一个FTP客户端。我觉得我大部分时间都关闭了项目,但是当我进行多个需要使用数据端口(列表、撤回等)的调用时,我遇到了问题。下面是中断的代码示例:

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

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

这段代码将在我第一次运行时毫无缺陷地执行,但如果我再试一次,它会挂在 'tmpclient = tmpserver 上。AcceptTcpClient();' line.它永远不会到达"gothere"打印语句。我相信这是因为我从同一端口上的同一台机器接收客户端,但我不确定。我尝试添加一个布尔值以确保 AcceptTcpClient() 只运行一次,但后来我收到运行时错误,Visual Studio 通知我我可能"在完成资源之前释放了资源"我预测这将是一个问题,但我如何判断服务器在关闭连接一次后是否重新建立连接?

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

如果我完全不清楚,我深表歉意,但我缺乏对该主题的了解,因此很难阐明我的问题。如果对问题是什么有任何困惑,我很乐意尝试解决它。

无法再次接受 TcpClient C#

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

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

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

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

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

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

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