c# - TCP 客户端连接

标签 c# tcp stream

我有一个应用程序,我为我的应用程序编写了分布在整个公司的应用程序,通过我们的 Windows 2003 服务器(运行 IIS 6.0)向我发送数据。小文本消息可以通过,但包含更多数据(大约 20 KB)的较大消息无法通过。

我将字节缓冲区设置为 TCP 客户端的缓冲区大小。我注意到服务器正在接收我的数据;但是,它只在接收例程中循环一次,而且我的大文件总是恰好等于缓冲区大小,或者在我们的服务器上为 8 KB。换句话说,在服务器关闭套接字连接之前,我的代码只完成了一个循环。

考虑到填充整个缓冲区可能存在问题,我尝试将读/写限制为仅 1 KB,但这只会导致我们的服务器在关闭连接前收到 1 KB 后关闭套接字。

我将服务器的错误消息发送回客户端,以便我查看。我从客户端收到的具体错误信息是:

“Unable to write data to the transport connection: An established connection was aborted by the software in your host machine.”

我更新了我的服务器应用程序,这样底层的 TCP 套接字将使用“keep alives”这一行:

client.Client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.KeepAlive, true);

现在,每当我尝试发送消息时,客户端都会收到错误:

“Unable to write data to the transport connection: An existing connection was forcibly closed by the remote host.”

我们的网络管理员告诉我他没有防火墙,也没有在我们的内部服务器上阻止任何端口。

谷歌搜索错误,我发现帖子建议人们尝试远程登录到服务器。我按照他们的指示远程登录到服务器,但我不确定如何响应:

C:> telnet Welcome to Microsoft Telnet Client

Escape Character is ‘CTRL+]’

Microsoft Telnet> open cpapp 500 Connecting To cpapp…

这就是我得到的全部。我从来没有收到错误,Microsoft 的 Telnet 屏幕最终会变成“按任意键继续……”——我猜它超时了,但我的代码以某种方式能够连接。

我在代码中和通过 Telnet 尝试了其他端口,包括 25、80 和 8080。Telnet 踢出端口 25,但无论我告诉它运行哪个端口,我的应用程序似乎都读取第一个循环。

这是我在客户端上运行的代码:

int sendUsingTcp(string location) {
  string result = string.Empty;
  try {
    using (FileStream fs = new FileStream(location, FileMode.Open, FileAccess.Read)) {
      using (TcpClient client = new TcpClient(GetHostIP, CpAppDatabase.ServerPortNumber)) {
        byte[] riteBuf = new byte[client.SendBufferSize];
        byte[] readBuf = new byte[client.ReceiveBufferSize];
        using (NetworkStream ns = client.GetStream()) {
          if ((ns.CanRead == true) && (ns.CanWrite == true)) {
            int len;
            string AOK = string.Empty;
            do {
              len = fs.Read(riteBuf, 0, riteBuf.Length);
              ns.Write(riteBuf, 0, len);
              int nsRsvp = ns.Read(readBuf, 0, readBuf.Length);
              AOK = Encoding.ASCII.GetString(readBuf, 0, nsRsvp);
            } while ((len == riteBuf.Length) && (-1 < AOK.IndexOf("AOK")));
            result = AOK;
            return 1;
          }
          return 0;
        }
      }
    }
  } catch (Exception err) {
    Logger.LogError("Send()", err);
    MessageBox.Show(err.Message, "Message Failed", MessageBoxButtons.OK, MessageBoxIcon.Hand, 0);
    return -1;
  }
}

这是我在服务器上运行的代码:

SvrForm.Server = new TcpListener(IPAddress.Any, CpAppDatabase.ServerPortNumber);

void Worker_Engine(object sender, DoWorkEventArgs e) {
  BackgroundWorker worker = sender as BackgroundWorker;
  string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), Application.CompanyName);
  if (Directory.Exists(path) == false) Directory.CreateDirectory(path);
  Thread.Sleep(0);
  string eMsg = string.Empty;
  try {
    SvrForm.Server.Start();
    do {
      using (TcpClient client = SvrForm.Server.AcceptTcpClient()) { // waits until data is avaiable
        if (worker.CancellationPending == true) return;
        client.Client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.KeepAlive, true);
        string location = Path.Combine(path, string.Format("Acp{0:yyyyMMddHHmmssff}.bin", DateTime.Now));
        byte[] buf = new byte[client.ReceiveBufferSize];
        try {
          using (NetworkStream ns = client.GetStream()) {
            if ((ns.CanRead == true) && (ns.CanWrite == true)) {
              try {
                int len;
                byte[] AOK = Encoding.ASCII.GetBytes("AOK");
                using (FileStream fs = new FileStream(location, FileMode.Create, FileAccess.Write)) {
                  do {
                    len = ns.Read(buf, 0, client.ReceiveBufferSize);
                    fs.Write(buf, 0, len);
                    ns.Write(AOK, 0, AOK.Length);
                  } while ((0 < len) && (ns.DataAvailable == true));
                }
                byte[] okBuf = Encoding.ASCII.GetBytes("Message Received on Server");
                ns.Write(okBuf, 0, okBuf.Length);
              } catch (Exception err) {
                Global.LogError("ServerForm.cs - Worker_Engine(DoWorkEvent)", err);
                byte[] errBuf = Encoding.ASCII.GetBytes(err.Message);
                ns.Write(errBuf, 0, errBuf.Length);
              }
            }
          }
        }
        worker.ReportProgress(1, location);
      }
    } while (worker.CancellationPending == false);
  } catch (SocketException) {
    // See MSDN: Windows Sockets V2 API Error Code Documentation for detailed description of error code
    e.Cancel = true;
  } catch (Exception err) {
    eMsg = "Worker General Error:\r\n" + err.Message;
    e.Cancel = true;
    e.Result = err;
  } finally {
    SvrForm.Server.Stop();
  }
}

为什么我的应用程序不继续从 TCP 客户端读取数据?我是否忽略了一些设置,告诉 Socket 在我完成之前保持打开状态?服务器代码永远不会看到异常,因为 TCP 客户端永远不会停止,所以我知道没有错误。

我们的网络管理员还没有获得副学士学位,所以如果结果证明这是服务器的问题,请在您的描述中详细说明如何解决这个问题,因为我们可能无法理解您在说什么。

很抱歉拖了这么久,但我想确保你们知道我在做什么 - 甚至可能从我的技术中获得一些信息!

感谢您的帮助! ~乔

最佳答案

您应该在发送的内容之前加上该内容的长度。您的循环假定所有数据都在循环执行之前发送,而实际上您的循环是在发送数据时执行的。有时线路上没有数据等待,因此循环终止;同时,内容仍在通过网络发送。这就是为什么你的循环只运行一次。

关于c# - TCP 客户端连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1256822/

相关文章:

c# - 如何计算 EF4 中 SaveChanges 的最佳大小?

c# - 动态创建VS Project

某些客户的 iOS TCP 套接字失去连接

delphi - 如何确定与 Indy 的连接是否仍然存在?

python解压缓冲区数据

c# - 如何在不使用 C# 中的正则表达式的情况下验证某些内容?

c# - 如何在指定的小时数内关闭控制台应用程序?

ffmpeg - 将输入流 mpg2 编码为输出流 h264 CBR

vb.net - 如何将流写入文件?

c# - 提高流式传输大型 (1-10 GB) 文件的速度 .Net Core