C#Tcp异步套接字数据读取逻辑

时间:2015-03-16 11:30:15

标签: c# c++ sockets

我正在研究一个C#Tcp异步套接字服务器程序,它只是读取套接字数据并将其放入文件中。现在问题是在发送实际文件内容之前我正在发送客户端名称和文件名。请注意,我正在通过以下方式使用简单的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. 
  }
}

1 个答案:

答案 0 :(得分: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);

    ...         
} 

一般反馈:

  • 此处不要使用BinaryWriter;只是Stream很好
  • 在文件流
  • 上使用using
  • 在一个字段中有一个缓存的委托实例,因此您每次都不需要new一个委托(如果您将目标实例作为状态传递,这甚至可以是static) LI>
  • 使用Path.Combine,最好提前一次,以避免大量字符串连接
  • 检查同步完成情况;在回调中,检查CompletedSynchronously并在true时立即退出;当开始工作时,抓住IAsyncResult,检查CompletedSynchronously,然后立即处理同一个帖子true
  • 考虑转移到较新的异步API - ReceiveAsync(这是一个非常重大的变化)
  • 来自IO方法的MessageBox