C# 通过单个端口传输多种数据类型(接收)

C# Transferring multiple data types over a single port (receiving)

问题

前几天,我对 C# 应用程序 有了一个 "amazing" 的想法。我不想为每种数据类型(文本、图像、文件)使用一个端口,而是想为所有三种数据类型使用一个单个端口 .我非常接近实现这个。

到目前为止,我有一个 TcpListener 监听端口 23722。当 TcpClient 连接时,我开始使用 StreamWriter.Write(datareceived); 将传入数据写入文件,数据以特定模式出现(每行代表一个图像、文本消息或文件):

dnett{This is a sample text message.)
dneti{NLtqmuvtGBdDY546 ... NLtqmuvtGBdDY546}
dnetf{Example.exe,NLtqmuvtGBdDY546 ... NLtqmuvtGBdDY546}

正如您从上面看到的图像和文件 在发送之前被转换为 Base64。要将它们转换回来,我会使用 byte[] tmp = Convert.FromBase64String(string),但问题是当数据仍在传入时,我无法逐行读取文件 (用 StreamWriter)。另一个问题是,我不知道哪些数据已被处理(例如:哪些文件已被写入文件系统)。


我需要的是:

  • 同时解决reading/writing个文件
  • 知道哪些数据已经被处理了

  • 另一种方法(不同的方法)

谢谢

顺便说一句,我只有 15 岁,英语不是我的第一语言,所以对于可能愚蠢的问题和上述问题中的错误,我深表歉意。

我也是初学者。但我认为您可以使用 ArrayList 来转换所有行,直到所有行都被读取和发送。因此,当您准备好并且文件已全部读取时,您可以保存它。如果您要问如何知道先发送哪种文件,请发送一个文件,您可以发送一个字符或一个字符串,以允许等待文件的其他程序识别将要恢复的文件。请原谅我的英语。我希望我能对你有所帮助。

通常,您会先发送 "message" 的大小,然后再发送实际的 "message"(来自服务器)。您可以将此扩展为先发送您的消息类型的大小,然后发送您的消息类型,然后发送实际消息的大小,然后发送该消息。

要回读,您需要这样做

using System;
using System.IO;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Binary;
using System.Threading;
using Newtonsoft.Json;
using Unity3DRemoteRendererClient.Helpers;

namespace Unity3DRemoteRendererClient.Communications.TCPCommunication {
 public sealed partial class TCPClientManager {
  public sealed class Receiver {
   private NetworkStream _stream;
   private Thread _thread;

   //Subscribe to this event if you want an event ever time data arrives.
   public event EventHandler < UnityToClientMessage > DataReceivedEvent;
   private static ManualResetEvent ShutDownEvent = new ManualResetEvent(false);

   public void Start(NetworkStream stream) {
    _stream = stream;
    _thread = new Thread(Run);
    _thread.Start();
   }

   private void Run() {
    try {
     // ShutdownEvent is a ManualResetEvent signaled by
     // Client when its time to close the socket.
     while (!ShutDownEvent.WaitOne(0)) {
      try {
       if (!_stream.DataAvailable) continue;

       //Read the first 4 bytes which represent the size of the message, and convert from byte array to int32
       var sizeinfo = new byte[4];
       _stream.Read(sizeinfo, 0, 4);
       var messageSize = BitConverter.ToInt32(sizeinfo, 0);

       //create a new buffer for the data to be read
       var buffer = new byte[messageSize];

       var read = 0;
       //Continue reading from the stream until we have read all bytes @messageSize
       while (read != messageSize) {
        read += _stream.Read(buffer, read, buffer.Length - read);
       }

       //I use flatbuffers, so you should deserialize yourself.
       var message = new UnityToClientMessage().FlatDeserialize(buffer);

       //raise data received event
       OnDataReceived(message);

      } catch (IOException ex) {
       // Handle the exception...
       throw;
      }
     }
    } catch (Exception ex) {
     // Handle the exception...
     throw;
    } finally {
     _stream.Close();
    }
   }

   private void OnDataReceived(UnityToClientMessage e) {
    EventHandler < UnityToClientMessage > handler = DataReceivedEvent;
    if (handler != null) {
     handler(this, e);
    }
   }

   public void ShutDown() {
    ShutDownEvent.Set();
   }

  }
 }
}

只需修改为先读取消息类型消息的大小,再读取实际消息即可。一旦收到描述即将到来的消息类型的消息,就可以执行 switch 语句,并相应地处理它。