TCP 客户端连接 [英] TCP Client Connection

查看:32
本文介绍了TCP 客户端连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an application that I have written for my application distributed throughout the company to send data to me through our Windows 2003 server (running IIS 6.0). Small text messages get through, but larger messages containing more data (about 20 KB) are not getting through.

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

I set the byte buffer to the TCP Client’s buffer size. I noticed that my data was being received on the server; however, it only looped through the receive routine once, and my large files were always exactly the size of the buffer size, or 8 KB on our server. In other words, my code only makes it through one loop before the server closes the socket connection.

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

Thinking there might be an issue with filling the whole buffer, I tried limiting my read/writes to just 1 KB but this only resulted in our server closing the socket after receiving 1 KB before closing the connection.

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

I send the server’s error message back to the client so I can view it. The specific error message that I receive from the client is:

无法将数据写入传输连接:已建立的连接被您的软件中止主机."

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

我更新了我的服务器应用程序,以便底层 TCP Socket 将使用keep alives"这一行:

I updated my server application so that the underlying TCP Socket would use "keep alives" with this line:

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

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

Now, whenever I attempt sending a message, the client receives the error:

无法将数据写入传输连接:现有连接是被远程主机强行关闭."

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

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

Our Network Administrator has told me that he does not have a firewall or any ports blocked on our internal server.

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

Googling the errors, I found posts suggesting people try to telnet into the server. I used their directions to telnet into the server, but I am not sure what to make of the response:

C:> telnet 欢迎来到微软Telnet 客户端

C:> telnet Welcome to Microsoft Telnet Client

转义字符是‘CTRL+]’

Escape Character is ‘CTRL+]’

Microsoft Telnet> 打开 cpapp 500正在连接到 cpapp...

Microsoft Telnet> open cpapp 500 Connecting To cpapp…

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

This is all I get. I never get an error, and Microsoft’s Telnet screen will eventually change to "Press any key to continue…" – I guess it times out, but my code is somehow able to connect.

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

I have tried other ports in code and through Telnet including 25, 80, and 8080. Telnet kicks out port 25, but my application seems to read the first loop no matter what port I tell it to run.

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

Here is my code that runs on the clients:

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;
  }
}

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

Here is my code that runs on the server:

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:
" + err.Message;
    e.Cancel = true;
    e.Result = err;
  } finally {
    SvrForm.Server.Stop();
  }
}

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

Why doesn’t my application continue reading from the TCP Client? Have I neglected to set something that tells the Socket to stay open until I have finished? The server code never sees an exception because the TCP Client is never stopped, so I know there is no error.

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

Our Network Administrator has not received his Associates Degree yet, so if it turns out to be an issue with the Server, kindly be detailed in your description of how to resolve this, because we might not understand what you’re saying.

我为这么长时间道歉,但我想确保你们那里的人知道我在做什么 - 甚至可能从我的技术中获得一些信息!

I apologize for this being so long, but I want to make sure you folks out there know what I'm doing - and maybe even gleam some information from my technique!

感谢您的帮助!~乔

推荐答案

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

You should precede the sent content with the length of that content. Your loop assumes that all of the data is sent before the loop executes, when in reality your loop is executing as the data is sent. There will be times when there is no data waiting on the wire, so the loop terminates; meanwhile, content is still being sent across the wire. That's why your loop is only running once.

这篇关于TCP 客户端连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆