【问题标题】:C# Tcp Async socket data read logicC# Tcp 异步套接字数据读取逻辑
【发布时间】:2015-03-16 19:55:37
【问题描述】:

我正在开发一个 C# Tcp Async 套接字服务器程序,该程序将简单地读取套接字数据并将其放入文件中。现在的问题是在发送实际文件内容之前,我正在发送客户端名称和文件名。请注意,我通过以下方式使用简单的 send() API 从 C++ MFC 应用程序发送这些数据。

CString csInitData = "Client_Name | File_Name <EOF>";
send(hSocket, (LPCTSTR)csInitData, csInitData.GetLength(), 0);

现在我如何在异步回调函数下面接收这些数据?无法弄清楚字节分解逻辑。

public void OnDataReceived(IAsyncResult ar)
{
  StateObject state = (StateObject)ar.AsyncState;
  Socket clientSocket = state.m_currentSocket;

  int bytesRead = clientSocket.EndReceive(ar);
  if (bytesRead > 0)
  {
    //HERE I WANT TO RECEIVE THOSE DATA AND CREATE FOLDER AND FILE WITH THOSE NAMES RECEIVED FROM CLIENT
    //Process 'state.dataBuffer'//DATA INSIDE THIS BYTE BUFFER

    string fileName = "";       //FILE NAME SHOULD GO HERE
    string folderName = "";     //CLIENT NAME SHOULD GO HERE

    BinaryWriter writer;

    if (!File.Exists(folderName+fileName))
    { 
      Directory.CreateDirectory(folderName);
      writer = new BinaryWriter(File.Open(folderName+fileName, FileMode.Create));
    } 
    else
    {
      writer = new BinaryWriter(File.Open(folderName+fileName, FileMode.Append));
    }

    writer.Write(state.dataBuffer, 0, bytesRead);
    writer.Flush();
    writer.Close();

    // Recursively receive the rest file. 
    try
    {
      clientSocket.BeginReceive(state.dataBuffer, 0, StateObject.BufferSize, 0, new AsyncCallback(OnDataReceived), state);
    }
    catch
    {
      if (!clientSocket.Connected)
      {
        MessageBox.Show("Catched from OnDataReceived!");
      }
    }
  }
  else
  {
    // Signal if all the file received. 
  }
}

【问题讨论】:

  • "无法确定字节分解逻辑。" - 你能更具体地说明你遇到的困难吗?有很多事情我会在这里做不同的事情,但我宁愿专注于你的主要问题。哪个是...?
  • 当我从客户端套接字接收数据时,我想将字节以字符串的形式保存到 单个变量中,以便我可以进一步处理它并继续读取下一个套接字数据.
  • 字符串不适合二进制数据;如果我正确理解您的评论,我怀疑您只是想使用 MemoryStream 作为缓冲区

标签: c# c++ sockets


【解决方案1】:

对于缓冲,听起来你想要MemoryStream

// Somewhere to put the data:
// for simplicity, I'll assume an instance field is fine; could
// also be tracked via async-state object, if preferred
private MemoryStream backlog = new MemoryStream();

if (bytesRead > 0)
{
    // we want to append, so move to the end
    backlog.Position = backlog.Length;

    // copy new data into the buffer
    backlog.Write(state.dataBuffer, 0, bytesRead);

    ...         
} 

一般反馈:

  • 不要在这里使用BinaryWriterStream 就可以了
  • 在文件流上使用using
  • 在字段中有缓存的委托实例,因此您不需要每次都 new 委托(如果您将目标实例作为状态传递,这甚至可以是 static
  • 使用Path.Combine,最好提前一次,以避免大量字符串连接
  • 检查同步完成;在回调中,检查CompletedSynchronously,如果是true,则立即退出;当开始工作时,捕获IAsyncResult,检查CompletedSynchronously,如果true,则立即在同一线程上处理
  • 考虑迁移到更新的异步 API - ReceiveAsync(不过,这是一个相当大的变化)
  • 不要通过 IO 方法MessageBox

【讨论】:

  • 好吧,我刚刚开始使用 C#。能否请您展示一个小样本。
  • MemoryStream 缓冲区的@hypheni?当然,给我一点时间编辑
  • 感谢您的快速响应。我从dotnetperls.com/memorystream 得到了一个例子。如果你能提供一个,那就太好了。
  • 但是,现在我必须从内存缓冲区解析数据。我想知道。如何解析到 即客户端发送的初始数据并将其保存在服务器端的单个变量中。
  • @hypheni 通过在每次“接收”时将数据复制到MemoryStream 中,当您到达末尾时:所有数据都在积压中。所以:从那里读。顺便说一句:读取到 不是“初始数据” - 它是 all 数据;如果套接字关闭,将不再接收数据。
猜你喜欢
  • 2018-03-25
  • 1970-01-01
  • 1970-01-01
  • 2016-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-24
相关资源
最近更新 更多